Win32:模态对话框没有返回焦点

时间:2009-05-28 23:06:32

标签: c++ c windows winapi

我正在编写一个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中的消息泵中。

我想过使用一个hashmap来映射指针,但我宁愿用GetWindowLong来做它。这可能吗?我已经尝试将对话框指针存储在DWL_USER中,但它没有帮助。

任何帮助都会受到赞赏,我仍然会围绕Win32。

编辑:我正在使用EndDialog

销毁对话框

编辑:我将指针存储在主窗口的GWL_USERDATA区域中,窗口没有使用它,我只在首次创建窗口时在WinClass :: WindowProc中修改它。如果我没有实例化对话框类,我知道正在正确访问指针,因为应用程序响应通过WindowProc和WM_COMMAND处理的菜单命令。

4 个答案:

答案 0 :(得分:5)

您不能将WindowProc用作DialogProc。 Window Procedures在它们不处理消息时调用DefWindowProc,并在它们执行时返回有意义的结果。 Dialog Procedures在不处理消息时返回FALSE,在DO处理时返回TRUE(除非他们处理WM_INITDIALOG时),如果他们有一个有意义的结果,他们需要从外部窗口程序返回,放在DWL_MSGRESULT

当您调用模式对话框函数DialogBox时,它会进入一个消息循环 - 它会将消息发送到线程中的所有窗口,以便所有窗口继续绘制和处理输入 - 当对话框关闭时(使用EndDialog) ,DialogBox过程应该返回。

当创建一个包装对话框的类时,通常的方法是将'this'指针传递给DialogBoxParam函数之一 - 可以直接从WM_INITDIALOG消息中提取。

答案 1 :(得分:0)

你是怎么关闭窗户的?你在使用DestroyWindow吗?当子窗口处于活动状态时,父窗口将被禁用。

答案 2 :(得分:0)

您正在保存指向lpCreateParams的指针。相关的内存块是否可能被释放或以其他方式被破坏?

答案 3 :(得分: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);
}