Страница 6 из 7
Класс ModalDialog
Центральным фрагментом для многократного использования программного обеспечения является класс ModalDialog. Он делает всю работу в своем конструкторе, вызывая функцию API DialogBoxParam. Параметр, который мы передаем диалоговому окну (фактически, его процедуре диалога) - указатель на фабрику контроллера. Процедура диалога определена как статический метод (не нужен указатель: процедура диалога вызывается из Windows, поэтому отсутствует доступ по указателю). class ModalDialog { public: ModalDialog (HINSTANCE hInst, HWND hwnd, int dlgResource, CtrlFactory *ctrlFactory) { _result = DialogBoxParam (hInst, MAKEINTRESOURCE (dlgResource), hwnd, (DLGPROC) ModalDialogProc, (LPARAM) ctrlFactory); }
static BOOL CALLBACK ModalDialogProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
bool IsOk () const { return (_result == -1)? false: _result != 0; }
private: int _result; }; | В заключение отметим, что процедура диалога, общая для всех типов диалогов, реализована так, чтобы ответить на три вида сообщений: WM_INITDIALOG, WM_COMMAND и WM_NOTIFY. Фактически, все они направляют эти сообщения к объекту - контроллеру. Он получает указатель на полиморфный объект контроллера вызывая в начале метод фабрики MakeController. Обратите внимание, что, из этой точки мы позволяем Windows, отследить указатель на контроллер. Мы сохраняем его как GWL_USERDATA - специальный длинный, который ассоциируется с каждым окном, в особенности с нашим диалогом, и доступен через его дескриптор окна. template <class T> inline T GetWinLong (HWND hwnd, int which = GWL_USERDATA) { return reinterpret_cast<T> (::GetWindowLong (hwnd, which)); }
template <class T> inline void SetWinLong (HWND hwnd, T value, int which = GWL_USERDATA) { ::SetWindowLong (hwnd, which, reinterpret_cast<long> (value)); } | Мы должны быть, хотя бы внимательными. Прежде всего мы должны освободить контроллер после того, как использовали его. Мы делаем это при обработке WM_DESTROY. |