[英]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.