Взаимодействие с элементами управления диалогового окна 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Взаимодействие с элементами управления диалогового окна



Несмотря на удобство средств DDX/DDV, полностью отказаться от обращения к ЭУ с помощью классов-оболочек ЭУ удается далеко не всегда. Например, может потребоваться вызывать функции CListBox для заполнения списка строками из OnInitDialog. Для этого необходим указатель на объект CListBox, представляющий список – ЭУ окна. Как его получить?

Указатель типа (CWnd*) для любого ЭУ окна можно получить функцией CWnd::GetDlgItem. Например, для включения запрещенной кнопки с независимой фиксацией IDC_CHECK, можно записать следующие вызовы:

CWnd* pWnd = GetDlgItem(IDC_CHECK); pWnd->EnableWindow(TRUE);

Этот исходный текст правилен, т.к. GetDlgItem возвращает указатель на CWnd, а функция EnableWindow является членом класса CWnd. Теперь рассмотрим следующий фрагмент текста:

CListBox* pListBox = (CListBox*)GetDlgItem(IDC_LIST); pListBox->AddString("Первый элемент"); pListBox->AddString("Второй элемент"); pListBox->AddString("Третий элемент");

Здесь для вызова функций-членов CListBox потребовалось выполнить преобразование типа для указателя, полученного от GetDlgItem. Явное преобразование типа указателей – плохой стиль программирования, и если ЭУ с идентификатором IDC_LIST в окне не окажется, может произойти серьезная ошибка доступа по нулевому указателю.

Лучшим решением является присоединение оконного дескриптора ЭУ к классу-оболочке ЭУ с помощью CWnd::Attach. Сначала надо создать объект класса ЭУ (например, CListBox), а затем динамически присоединить к нему ЭУ, например:

CListBox wndListBox; wndListBox.Attach(GetDlgItem(IDC_LIST)->m_hWnd); wndListBox.AddString("Первый элемент"); wndListBox.AddString("Второй элемент"); wndListBox.AddString("Третий элемент"); wndListBox.Detach();

Т.к. объект CListBox был создан в стеке, очень важно вызывать Detach до того, как объект CListBox будет уничтожен. Иначе деструктор CListBox удалит ЭУ и список исчезнет из диалогового окна.

Чтобы не писать вызовы функций присоединения/отсоединения ЭУ от объекта-оболочки, можно сопоставить их с помощью функции DDX_Control. Например, чтобы связать переменную-член m_wndListBox класса CListBox со списком с идентификатором IDC_LIST, в DoDataExchange надо внести вызов:

DDX_Control(pDX, IDC_LIST, m_wndListBox);

Теперь добавлять строки в список можно, просто вызывая AddString у m_wndListBox:

m_wndListBox.AddString("Первый элемент"); m_wndListBox.AddString("Второй элемент"); m_wndListBox.AddString("Третий элемент");

Вызовы DDX_Control в функцию DoDataExchange удобно добавлять с помощью ClassWizard. Для этого надо перейти на закладку Member Variables и с помощью кнопки Add Variable добавить в класс переменную-член. Но в окне Add Member Variable (рис. 8.5) в списке Category надо вместо Value выбрать Control. Затем в списке Variable Type выберите класс ЭУ и нажмите кнопку OK. Если после выхода из ClassWizard вы посмотрите на исходный текст диалогового класса, то увидите, что ClassWizard добавил в класс переменную-член, а также вызов функции DDX_Control для связи этой переменной с элементом управления.

 

Окна свойств

Окна свойств (диалоговые окна с закладками) часто используются в Windows для компактного представления большого количества ЭУ. Эти диалоговые окна реализованы в библиотеке стандартных ЭУ Windows 95. На уровне API для реализации окон свойств требуется довольно много усилий, которые существенно упрощаются при использовании MFC. Оказывается, что добавить окно свойств почти также легко, как и обычное диалоговое окно.

Окна свойств в MFC представлены двумя классами: CPropertySheet и CPropertyPage. CPropertySheet (унаследован от CWnd) представляет собственно окно свойств, а CPropertyPage (унаследован от CDialog) – отдельную страницу свойств. Оба класса описаны в файле Afxdlgs.h. Как и диалоговые окна, окна свойств могут быть модальными и немодальными. Модальное окно создается вызовом CPropertySheet::DoModal, а немодальное –CPropertySheet::Create.

Общий порядок создания модального окна свойств следующий:

1) Для каждой страницы свойств надо создать отдельный шаблон диалогового окна, задающий содержимое и свойства страницы. Указанный в шаблоне заголовок окна будет выводиться как название закладки в окне свойств.

2) Для каждой страницы свойств надо создать подкласс CPropertyPage, в котором, аналогично обычному диалоговому окну, можно завести открытые переменные-члены и связать их с ЭУ страницы с помощью DDX/DDV.

3) Для представления окна свойств создается подкласс CPropertySheet. Для работы окна должны быть созданы объекты этого класса, а также объекты всех классов-страниц, определенных на шаге 2). Для добавления страниц в окно свойств следует пользоваться функцией CPropertySheet::AddPage.

4) Окно свойств выводится на экран вызовом его функции-члена DoModal.

Для упрощения создания окон свойств большинство программистов объявляют объекты страниц свойств как переменные-члены класса окна свойств. Эти объекты привязываются к окну свойств из конструктора вызовами AddPage для каждой страницы свойств. Пример подобной реализации окна свойств приведен ниже:

class CFirstPage: public CPropertyPage { public: CFirstPage(): CPropertyPage(IDD_FIRSTPAGE) {;} // Объявление переменных-членов CFirstPage protected: virtual void DoDataExchange(CDataExchange*); };   class CSecondPage: public CPropertyPage { public: CSecondPage(): CPropertyPage(IDD_SECONDPAGE) {;} // Объявление переменных-членов CSecondPage protected: virtual void DoDataExchange(CDataExchange*); };   class CMyPropertySheet: public CPropertySheet { public: CFirstPage m_firstPage; // Первая страница CSecondPage m_secondPage; // Вторая страница // Страницы добавляются в окно из конструктора CMyPropertySheet(LPCTSTR pszCaption, CWnd* pParentWnd = NULL): CPropertySheet(pszCaption, pParentWnd, 0) { AddPage(&m_firstPage); AddPage(&m_secondPage); } };

В данном примере страницы свойств представлены классами CFirstPage и CSecondPage. С ними связаны ресурсы шаблонов диалоговых окон с идентификаторами IDD_FIRSTPAGE и IDD_SECONDPAGE. При такой структуре классов окна свойств, вызвать его из приложения можно всего двумя операторами:

CMyPropertySheet ps("Свойства"); ps.DoModal();

Как и CDialog::DoModal, функция CPropertySheet::DoModal возвращает IDOK или IDCANCEL.

В шаблонах диалоговых окон для страниц свойств не должно быть кнопок OK и Отмена, т.к. MFC добавляет их в окно свойств автоматически. Также в него добавляется кнопка Применить (Apply) и, возможно, Помощь (Help). При выводе окна свойств на экран кнопка Применить сначала запрещена, а включается она после того, как какая-либо страница свойств вызовет функцию-член CPropertyPage::SetModified с параметром TRUE. SetModified надо вызывать при каждом изменении параметров страницы свойств – например, при изменении текста в строке ввода или при переключении кнопки с зависимой фиксацией. Для обработки нажатия кнопки Применить надо добавить в класс страницы свойств обработчик ON_BN_CLICKED для кнопки с идентификатором ID_APPLY_NOW. Этот обработчик должен вызвать UpdateData(TRUE) для обновления значений переменных-членов страницы свойств и, возможно, передать эти значения окну-владельцу окна свойств. После этого, считая, что изменения учтены, надо запретить кнопку Применить вызовом SetModified(FALSE) – по одному разу для каждой страницы свойств.

 

Стандартные диалоговые окна Windows

Ряд диалоговых окон, предназначенных для выполнения часто встречающихся в различных приложениях команд, был реализован как часть операционной системы. В MFC есть классы-оболочки для этих окон, они перечислены в табл. 8.2.

Таблица 8.2. Классы стандартных диалоговых окон

Имя класса Представляемые диалоговые окна
CFileDialog Открыть и Сохранить как
CPrintDialog Печать
CPageSetupDialog Макет страницы
CFindReplaceDialog Поиск и Замена (текста)
CColorDialog Выбор цвета
CFontDialog Выбор шрифта

При программировании на уровне API для вызова стандартного окна требуется заполнить некоторую структуру и передать ее функции API, например,::GetOpenFileName. После возврата из этой функции введенные пользователем параметры будут сохранены в передававшейся функции структуре. MFC упрощает интерфейс стандартных окон, заполняя большинство полей структуры "по умолчанию" и автоматически извлекая из нее данных после закрытия диалогового окна. Например, получить имя открываемого файла в MFC-приложении можно так:

TCHAR szFilters[] = "Текстовые файлы (*.txt)¦*.txt¦Все файлы (*.*)¦*.*¦¦"; CFileDialog dlg(TRUE, "txt", "*.txt", OFN_FILEMUSTEXIST ¦ OFN_HIDEREADONLY, szFilters); if (dlg.DoModal() == IDOK) { filename = dlg.GetPathName(); // Открытие файла и чтение данных из него ... }

У конструктора CFileDialog параметр TRUE обозначает, что надо выводить окно Открыть, а не Сохранить как. Параметры "txt" и "*.txt" задают расширение файла "по умолчанию" – то расширение, которое будет добавлено к имени файла, если пользователь не укажет его явно. Значения OFN_... – это битовые флаги, задающие свойства диалогового окна. OFN_FILEMUSTEXIST задает, что требуется проверять наличие файла с введенным пользователем именем и не принимать имена несуществующих файлов. OFN_HIDEREADONLY скрывает флажок Только чтение, который по умолчанию появляется в диалоговом окне. Строка szFilters задает типы файлов, которые может выбирать пользователь. После возврата из DoModal, полный путь к выбранному файлу можно получить функцией CFileDialog::GetPathName. Функция CFileDialog::GetFileName возвращает часть имени файла без пути, а GetFileTitle – часть имени файла без пути и без расширения.

Изменить поведение класса CFileDialog или других стандартных диалоговых классов можно несколькими способами. Во-первых, можно задать параметры окна в конструкторе класса (битовых флагов OFN_... больше 10-ти, все они влияют на внешний вид и поведение окна). Например, чтобы вызвать окно Открыть для получения имени только одного существующего файла, конструктор вызывается так:

CFileDialog dlg(TRUE, "txt", "*.txt", OFN_FILEMUSTEXIST ¦ OFN_HIDEREADONLY, szFilters);

Чтобы пользователь мог выделить несколько файлов, добавляется всего один флаг:

CFileDialog dlg(TRUE, "txt", "*.txt", OFN_FILEMUSTEXIST ¦ OFN_HIDEREADONLY ¦ OFN_ALLOWMULTISELECT, szFilters);

После возврата из DoModal список имен выбранных файлов хранится в буфере, на который указывает поле структуры m_ofn.lpstrFile. Их можно перебрать с помощью функций CFileDialog::GetStartPosition и GetNextPathName.

В целом, классы MFC для стандартных диалоговых окон очень просты в использовании, особенно если пользоваться ими непосредственно и не создавать собственных подклассов.



Поделиться:


Последнее изменение этой страницы: 2016-08-01; просмотров: 304; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.191.5.239 (0.008 с.)