Немодальный диалог создаётся с использованием функции Createи разрушается вызовом DestroyWindow. Реализация обоих методов также достаточно очевидна.
// modeless dialogs
HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL) {
ATLASSERT(m_hWnd == NULL);
_Module.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT*)this);
#ifdef _DEBUG
m_bModal = false;
#endif //_DEBUG
HWND hWnd = ::CreateDialogParam(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::IDD),
hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam);
ATLASSERT(m_hWnd == hWnd);
return hWnd;
}
BOOL DestroyWindow() {
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(!m_bModal); // must not be a modal dialog
return ::DestroyWindow(m_hWnd);
}
С учётом всего сказанного, типичный класс диалога, порождённый от CDialogImpl<>, выглядит так (в качестве параметра шаблона задаётся имя класса, который вы порождаете).
class CMyDialog : public CDialogImpl {
public:
enum { IDD = IDIDD_MY_DIALOG };
BEGIN_MSG_MAP(CMyDialog)
// Карта сообщений
END_MSG_MAP()
};
Обратите внимание, что константа IDDописывается в секции public. Если описать её в private-секции, функция базового класса CDialogImpl<>::DoModalне сможет к ней обратиться, что приведёт к ошибке.
Далее полученный класс можно использовать для создания как модальных, так и немодальных диалогов, например:
// Создаём модальный диалог
CMyDialog modal;
modal.DoModal();
// Создаём немодальный диалог
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*)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*)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 dlg;
dlg.DoModal();
Ещё раз подчеркну, что класс CSimpleDialog<>не содержит реализации метода Create, а поэтому не позволяет создавать немодальные диалоги. Методы EndDialogи DestroyWindowтакже отсутствуют.
Класс CWinDataExchange<>: механизм DDX в стиле WTL
Механизм динамического обмена данными (DDX – Dynamic Data eXchange) используется для обмена данными между контролами и переменными вашей программы. Термин DDX был введён в MFC, хотя сам механизм под разными названиями существует и в других библиотеках. В WTL он также присутствует. Его реализация содержится в классе CWinDataExchange<>.
Читать дальше