Рейтинговые книги
Читем онлайн Программирование на Visual C++. Архив рассылки - Алекс Jenter

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 91 92 93 94 95 96 97 98 99 ... 156

CMyDialog modeless;

modeless.Create(HWND_DESKTOP);

Класс CAxDialogImpl<>

Класс CAxDialogImpl<> очень похож на предыдущий. Вся разница в том, что вместо функции DialogBoxParam он использует функцию AtlAxDialogBox, а вместо функции CreateDialogParam – функцию AtlAxCreateDialog:

// modal dialogs

int DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL) {

 ATLASSERT(m_hWnd == NULL);

 _Module.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT<TBase>*)this);

#ifdef _DEBUG

 m_bModal = true;

#endif //_DEBUG

 return AtlAxDialogBox(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::IDD),

  hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam);

}

...

// modeless dialogs

HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL) {

 ATLASSERT(m_hWnd == NULL);

 _Module.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT<TBase>*)this);

#ifdef _DEBUG

 m_bModal = false;

#endif //_DEBUG

 HWND hWnd = AtlAxCreateDialog(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::IDD),

  hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam);

 ATLASSERT(m_hWnd == hWnd);

 return hWnd;

}

Эти функции, в отличие от своих аналогов из Win32 API, могут создавать диалоги, содержащие ActiveX-контролы. Мы не будем рассматривать их реализацию, поскольку тема использования ActiveX-контролов выходит за рамки данной статьи.

Класс CSimpleDialog<>

Чтобы создавать диалоги на базе класса CDialogImpl<>, необходимо каждый раз порождать от него собственные классы. Это довольно утомительно. Класс CSimpleDialog<> предназначен для отображения простейших модальных диалогов, содержащих только статическую информацию и стандартные кнопки, такие как "OK" и "Отмена". Кроме функции DoModal, которая реализована почти так же, как в классе CDialogImpl<>, этот класс предоставляет собственную карту сообщений и обработчики OnInitDialog и OnCloseCmd. Последний вызывается в ответ на нажатие любой кнопки со стандартным идентификатором (IDOK, IDCANCEL, IDABORT, IDRETRY, IDIGNORE, IDYES или IDNO) и закрывает диалог.

Обратите внимание, что идентификатор ресурса диалога в классе CSimpleDialog<> задаётся не как константа, а как первый параметр шаблона. Благодаря этому класс можно использовать, не порождая от него собственных классов. Если, к примеру, вы нарисовали в редакторе диалоговое окно About и назначили ему идентификатор IDD_ABOUT, отобразить его можно, используя класс CSimpleDialog<> напрямую:

CSimpleDialog<IDD_ABOUT> dlg;

dlg.DoModal();

Ещё раз подчеркну, что класс CSimpleDialog<> не содержит реализации метода Create, а поэтому не позволяет создавать немодальные диалоги. Методы EndDialog и DestroyWindow также отсутствуют.

Класс CWinDataExchange<>: механизм DDX в стиле WTL

Механизм динамического обмена данными (DDX – Dynamic Data eXchange) используется для обмена данными между контролами и переменными вашей программы. Термин DDX был введён в MFC, хотя сам механизм под разными названиями существует и в других библиотеках. В WTL он также присутствует. Его реализация содержится в классе CWinDataExchange<>.

Прежде чем рассказывать про класс CWinDataExchange<>, скажу несколько слов об общих принципах реализации дополнительной функциональности в WTL.

Обычно дополнительные возможности WTL реализуются в отдельных классах. Чтобы получить доступ к этим возможностям, необходимо произвести свой класс от всех классов WTL, содержащих нужную нам функциональность. Далее каждый из базовых классов конфигурируется с помощью соответствующей карты (map), которая составляется из специально предусмотренных для этой цели макросов. Обычно карта начинается макросом BEGIN_XXX_MAP и заканчивается макросом END_XXX_MAP (XXX обозначает некоторый идентификатор, разъясняющий назначение карты). Между ними располагаются все остальные макросы карты.

Некоторые механизмы WTL, подключённые к нашему классу, требуют также начальной инициализации, которую можно выполнить, например, в обработчике сообщения WM_INITDIALOG.

Настроив нужные нам механизмы WTL, мы можем использовать их, вызывая или переопределяя предусмотренные для этой цели методы.

Вернёмся к механизму DDX. Чтобы использовать его, включите в список базовых классов вашего диалога (или другого окна, содержащего контролы) класс CWinDataExchange<> (описан в файле atlddx.h). В качестве параметра шаблона задаётся имя вашего производного класса. Например:

class CMyDialog : public CDialogImpl<CMyDialog>, public CWinDataExchange<CMyDialog> {

 …

};

Следующий шаг – включить в public-секцию вашего класса карту DDX. Каждая строчка в этой карте связывает идентификатор контрола с некоторой переменной в вашей программе. Обычно это переменная-член класса, но она может быть и глобальной/статической. В обмене могут участвовать числовые или текстовые данные с ограничениями или без них. Список макросов, из которых строится карта DDX, приведён в таблице 1.

Макрос Описание BEGIN_DDX_MAP(thisClass) Начало карты DDX. thisClass – имя класса, в котором содержится карта. DDX_TEXT(nID, var) Связывает строковую переменную var с контролом nID (здесь и далее nID – это идентификатор контрола). Переменная var может иметь тип TCHAR*, BSTR, CComBSTR или CString. Обмен данными осуществляется при помощи функций SetWindowText и GetWindowText. Чаще всего макрос используется для статических контролов и полей ввода, хотя может применяться и с другими окнами. DDX_TEXT_LEN(nID, var, len) Аналогичен предыдущему, но длина строки ограничивается значением len. Попытка передать строку, длина которой превышает len, приведёт к ошибке валидации (об ошибках немного позже). DDX_INT(nID, var) Связывает целочисленную переменную var с контролом nID. DDX_INT_RANGE(nID, var, min, max) Аналогичен предыдущему, но передаваемое значение должно лежать в диапазоне от min до max. Невыполнение этого условия приведёт к ошибке валидации. DDX_UINT(nID, var) Связывает целочисленную беззнаковую переменную var с контролом nID. DDX_UINT_RANGE(nID, var, min, max) Аналогичен предыдущему, но передаваемое значение должно лежать в диапазоне от min до max. Невыполнение этого условия приведёт к ошибке валидации. DDX_FLOAT(nID, var) Связывает переменную с плавающей точкой var с контролом nID. var может иметь тип float или double. Макрос DDX_FLOAT будет доступен, только если вы определите макрос _ATL_USE_DDX_FLOAT перед включением заголовочного файла atlddx.h. DDX_FLOAT_RANGE(nID, var, min, max) Аналогичен предыдущему, но передаваемое значение должно лежать в диапазоне от min до max. Невыполнение этого условия приведёт к ошибке валидации. DDX_CONTROL(nID, obj) Связывает объект obj с контролом nID. Для связывания используется метод obj.SubclassWindow, поэтому объект должен принадлежать классу CWindowImplBaseT<> или производному от него. DDX_CHECK(nID, var) Привязывает переменную var типа int к флагу checked кнопки nID. Для обмена данными используются сообщения BBM_SETCHECK и BM_GETCHECK. DDX_RADIO(nID, var) Связывает переменную var типа int с группой переключателей. Контрол nID должен быть первым в группе. END_DDX_MAP() Этот макрос завершает карту DDX. Не имеет параметров.

Рассмотрим пример карты DDX для диалога, который позволяет вводить имя, адрес и номер телефона.

BEGIN_DDX_MAP(CMyDialog)

 DDX_TEXT_LEN(IDC_NAME, m_name, 20)

 DDX_TEXT(IDC_ADDRESS, m_address)

 DDX_UINT_RANGE(IDC_PHONE, m_phone, 0, 9999999)

END_DDX_MAP()

ПРИМЕЧАНИЕ

Если вы использовали MFC, вы, вероятно, заметили сходство карты DDX с виртуальной функцией CWnd::DoDataExchange. Они действительно похожи. Одно отличие состоит в том, что макросы WTL не используют вспомогательную структуру, аналогичную CDataExchange из mfc. Это несколько упрощает их использование. Второе отличие – в WTL собственно обмен и валидация объединены вместе, а в MFC им соответствуют различные функции (DDX_* для обмена данными и DDV_* для валидации).

Вот и всё. Никакой дополнительной инициализации механизм DDX в WTL не требует. Чтобы выполнить обмен данными, используйте функцию DoDataExchange. Вот её прототип:

1 ... 91 92 93 94 95 96 97 98 99 ... 156
На этой странице вы можете бесплатно читать книгу Программирование на Visual C++. Архив рассылки - Алекс Jenter бесплатно.
Похожие на Программирование на Visual C++. Архив рассылки - Алекс Jenter книги

Оставить комментарий