【问题标题】:Win32: Modal dialog not returning focusWin32:模态对话框不返回焦点
【发布时间】:2010-10-29 17:55:26
【问题描述】:

我正在编写一个win32 wrapper classes,主要是为了学习更多关于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 区域中,Windows 不使用该区域,并且仅在首次创建窗口时在 WinClass::WindowProc 中对其进行修改。如果我不实例化对话框类,我知道指针被正确访问,因为应用程序响应通过 WindowProc 和 WM_COMMAND 处理的菜单命令。

【问题讨论】:

    标签: c++ c windows winapi


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        您不能将 WindowProc 用作 DialogProc。窗口过程在不处理消息时调用 DefWindowProc,并在处理时返回有意义的结果。 对话框过程在不处理消息时返回 FALSE,在处理时返回 TRUE(处理WM_INITDIALOG 时除外),如果它们有需要从外部窗口过程返回的有意义的结果,则放置在DWL_MSGRESULT

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

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

        【讨论】:

          【解决方案4】:
          //静态方法 BOOL CALLBACK WinClass::DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { // 在 GWL_USERDATA 中存储 *this* 指针 如果(味精 == WM_INITDIALOG) { ::SetWindowLongPtr(hwnd, DWLP_USER, reinterpret_cast(lParam)); m_hWnd = hWnd; // 我假设你真的不想继续传递 hwnd } WinClass* wnd = reinterpret_cast(::GetWindowLongPtr(hwnd, GWL_USERDATA)); 如果 (wnd) 返回 wnd->DlgProcImpl(umsg, wParam, lParam); 返回错误; } BOOL WinClass::DlgProcImpl(UINT uMsg, WPARAM wParam, LPARAM lParam) { 开关(微信) { // 你的代码在这里 返回错误; } 返回错误; } INT_PTR WinClass:DoModalDialog(HINSTANCE hInst, HWND hwndParent, LPCTSTR 模板) { 返回 ::DialogBoxParam(hInst, 模板, hwndParent, WinClass::DlgProc, this); }

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2010-11-07
            • 1970-01-01
            • 1970-01-01
            • 2012-04-12
            • 1970-01-01
            • 2016-03-06
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多