2009-05-28 3 views
0

Я пишу классы оболочки win32, в основном, чтобы узнать больше о программировании win32. Чтобы обойти проблему обратных вызовов c-стиля, следующий способ хранит/извлекает указатель с помощью SetWindowLong/GetWindowLong и передает его фактическому winproc.Win32: Модальный диалог, не возвращающий фокус

LRESULT CALLBACK WinClass::WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    // On window creation, WindowProc receives lParam as a LPCREATESTRUCT 
    // Store *this* pointer as long in GWL_USERDATA 
    if (msg == WM_NCCREATE) 
     ::SetWindowLong(hwnd, GWL_USERDATA, reinterpret_cast<long>(reinterpret_cast<LPCREATESTRUCT>(lParam)->lpCreateParams)); 

    // Retrieve the pointer 
    WinClass *wnd = reinterpret_cast<WinClass*>(::GetWindowLongPtr(hwnd, GWL_USERDATA)); 

    // Call the actual winproc function 
    if (wnd) 
     return wnd->WndProc(hwnd, msg, wParam, lParam); 
    // Default to DefWindowProc message handler function 
    return ::DefWindowProc(hwnd, msg, wParam, lParam); 
} 

Winclass класс обвести главное окно, созданное CreateWindowEx. Одна и та же функция WindowProc является частью MDlgClass, обертывающей модальный диалог. Я вызываю диалоговое окно, как этот

DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(id), hwnd, DialogProc); 

Если я передаю NULL как hWndParent, диалог работает нормально, как немодальной диалог, но если я прохожу HWND, дескриптор главного окна, как hWndParent диалог работает правильно, как модальный диалог. Однако, когда я закрываю диалог, он не передает управление обратно в основное родительское окно? Отладка в Visual Studio показывает его зависание в насосе сообщений в WinMain.

Я думал об использовании хэш-карты для отображения указателей, но я бы предпочел сделать это с помощью GetWindowLong и т. Д. Возможно ли это? Я попытался сохранить указатель диалога в DWL_USER, но он не помогает.

Любая помощь будет оценена по достоинству, я все еще получаю голову вокруг Win32.

EDIT: Я разрушив диалог, используя EndDialog

EDIT: Я хранить указатель в GWL_USERDATA области главного окна, которое не используется окон, и я только изменить его в WinClass :: WindowProc при первом создании окна. Если я не создаю экземпляр класса диалога, я знаю, что указатель обращается правильно, так как приложение отвечает на команды меню, обработанные через WindowProc и WM_COMMAND.

ответ

0

Как вы закрываете окно? Вы используете DestroyWindow? Пока дочернее окно будет жить, родительское окно будет отключено.

0

Вы сохраняете указатель на lpCreateParams. Возможно ли, что связанный блок памяти освобождается или иным образом уничтожается?

4

Вы не можете использовать WindowProc как DialogProc. Процедуры Window вызывают DefWindowProc, когда они не обрабатывают сообщение и возвращают значимый результат, когда они это делают. Диалоговые процедуры возвращают FALSE, когда они не обрабатывают сообщение, возвращают TRUE, когда они DO (за исключением случаев, когда они обрабатывают WM_INITDIALOG), и если они имеют значимый результат, который им нужно вернуть из процедуры внешнего окна, которая помещается в DWL_MSGRESULT.

Когда вы вызываете функцию модального диалогового окна, DialogBox, он вводит цикл пересылки сообщений, который отправляет сообщения всем окнам в потоке, чтобы все окна продолжали рисовать и обрабатывать ввод - когда диалог закрыт (используя EndDialog), процедура DialogBox должна вернуться.

При создании класса для обертывания диалоговых окон обычным методом является передача указателя 'this' к одной из функций DialogBoxParam, которая может быть непосредственно извлечена из сообщения WM_INITDIALOG.

0
 
//static method 
BOOL CALLBACK WinClass::DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    // Store *this* pointer as long in GWL_USERDATA 
    if (msg == WM_INITDIALOG) 
    { 
     ::SetWindowLongPtr(hwnd, DWLP_USER, reinterpret_cast(lParam)); 
     m_hWnd = hWnd; // I assume you really don't want to keep passing the hwnd around 
    } 

    WinClass* wnd = reinterpret_cast(::GetWindowLongPtr(hwnd, GWL_USERDATA)); 
    if (wnd) 
     return wnd->DlgProcImpl(umsg, wParam, lParam); 
    return FALSE; 
} 

BOOL WinClass::DlgProcImpl(UINT uMsg, WPARAM wParam, LPARAM lParam) 
{ 
    switch (uMsg) 
    { 
     // your code goes here 

      return FALSE; 
    } 

    return FALSE; 
} 

INT_PTR WinClass:DoModalDialog(HINSTANCE hInst, HWND hwndParent, LPCTSTR template) 
{ 
    return ::DialogBoxParam(hInst, template, hwndParent, WinClass::DlgProc, this); 
} 

Смежные вопросы