функция StartDialogProc назначается диалогу при его создании. Для этого её адрес передаётся функциям, подобным DialogBox и CreateDialog, или задаётся в качестве хука для стандартных диалогов. Получив управление, эта функция извлекает хэндл диалога из объекта _Module и сохраняет его в переменной m_hWnd, затем инициализирует переходник и передаёт управление штатной диалоговой процедуре DialogProc, которая и выполняет дальнейшее обслуживание диалога. Каждое полученное сообщение она "пропускает" через карту сообщений вызовом ProcessWindowMessage. Возвращаемое после обработки сообщения значение интерпретируется
в зависимости от типа сообщения. Тем самым обеспечивается небольшое, но весьма приятное удобство: программист не должен помнить, каким образом нужно передать операционной системе LRESULT из диалоговой процедуры (напрямую или с помощью SetWindowLong). Достаточно вернуть его из функции-обработчика, а об остальном позаботится WTL.
Поскольку диалоги, как и все остальные окна, используют для обработки сообщений функцию ProcessWindowMessage, вы можете использовать для её создания уже знакомые вам макросы карты сообщений.
После уничтожения диалога WTL вызывает виртуальную функцию OnFinalMessage. Вы можете переопределить её в производном классе и возложить на неё "очистительные" работы. Следует только иметь в виду, что во время работы этой функции диалог уже не существует, и даже переменная m_hWnd содержит NULL. Поэтому в функции OnFinalMessage нельзя, к примеру, загружать данные из контролов диалога в переменные.
Класс CDialogImpl<>
Класс CDialogImpl<> – основное средство для работы с диалогами в WTL. Он используется как с модальными, так и с немодальными диалогами. Соответственно, в нём содержатся обёртки для функций DialogBoxParam, EndDialog, CreateDialogParam и DestroyWindow. Механизм обработки сообщений наследуется от класса CDialogImplBaseT<>.
Для создания модального диалога используется метод DoModal. Уничтожить модальный диалог можно, используя метод EndDialog (можно вызывать этот метод из любого обработчика сообщений, в том числе из обработчика сообщения WM_INITDIALOG). Реализация обоих методов более чем прямолинейна:
// modal dialogs
int DoModal(HWND hWndParent = ::GetActiveWindow, LPARAM dwInitParam = NULL) {
Здесь следует обратить внимание всего на две вещи. Во-первых, в качестве диалоговой процедуры задаётся StartDialogProc. Благодаря этому к создаваемому диалогу подключается механизм обработки сообщений, рассмотренный в предыдущем разделе. Во-вторых, в качестве идентификатора ресурса диалога используется константа IDD. Вам необходимо определить её в производном классе, чтобы WTL знала, какой диалог требуется создать. В принципе, можно сделать IDD и статической переменной производного класса, но прибегать к этому приёму на практике приходится не часто.