簡體   English   中英

Win32:模式對話框未返回焦點

[英]Win32: Modal dialog not returning focus

我正在編寫Win32包裝器類,主要是為了學習有關Win32編程的更多信息。 為了解決c風格的回調問題,以下方法使用SetWindowLong / GetWindowLong存儲/檢索指針,並將其傳遞給實際的winproc。

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有所了解。

編輯:我正在使用EndDialog銷毀對話框

編輯:我將指針存儲在主窗口的GWL_USERDATA區域中,窗口不使用它,並且僅在首次創建窗口時才在WinClass :: WindowProc中對其進行修改。 如果我不實例化對話框類,則我知道該指針已正確訪問,因為該應用程序響應通過WindowProc和WM_COMMAND處理的菜單命令。

您不能將WindowProc用作DialogProc。 窗口過程不處理消息時將調用DefWindowProc,並在處理過程時返回有意義的結果。 對話框過程在不處理消息時返回FALSE,在不執行消息時返回TRUE(處理WM_INITDIALOG時除外),並且如果它們有有意義的結果需要從外部窗口過程返回,則將其放置在DWL_MSGRESULT

當您調用模式對話框函數DialogBox時,它將進入一個消息泵送循環-它將消息分發到線程中的所有窗口,以便所有窗口繼續繪制和處理輸入-當對話框關閉(使用EndDialog)時,該DialogBox程序應該返回。

在創建用於包裝對話框的類時,通常的方法是將“ this”指針傳遞給DialogBoxParam函數之一-可以直接從WM_INITDIALOG消息中提取該WM_INITDIALOG

您如何關閉窗戶? 您正在使用DestroyWindow嗎? 子窗口處於活動狀態時,父窗口將被禁用。

您正在保存一個指向lpCreateParams的指針。 相關的內存塊是否可能被釋放或以其他方式破壞?

//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);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM