从 MDI 客户区分离 MDI 子项时无法单击 controls/menu

Can't click on controls/menu when detach MDI child out of MDI client area

整个示例项目可以在这里找到:Sample project

普通 MDI 子级:

MDI 子级脱离 MDI 客户区:

问题是在 MDI child 分离后,我无法再点击 menu/controls。

我认为一种方法是子类化 MDI 应用程序的 winproc,然后捕获消息并重定向它们(如 this one)。但是我不知道从哪里开始。

欢迎任何想法/其他方法!

我用来分离 MDI child 的代码:

HWND MDIHwnd = pMainFrame->m_hWndMDIClient;
HWND mdiChildHwnd = GetWindow(MDIHwnd, GW_CHILD);

unsigned int style = GetWindowLongPtr(mdiChildHwnd, GWL_STYLE);
style = (style & (~WS_CHILD) | WS_POPUP);
SetWindowLongPtr(mdiChildHwnd, GWL_STYLE, style);

WaitForInputIdle(mdiChildHwnd, INFINITE);
SetParent(mdiChildHwnd, NULL);

WaitForInputIdle(mdiChildHwnd, INFINITE);
SetWindowLongPtr(mdiChildHwnd, GWLP_HWNDPARENT, (long)MDIHwnd);

这里有高手说不可能,我找到了解决方法。
经验教训:当有人说这不可能时,这意味着只有他们不可能,而不是你。

整个示例项目可以在这里找到:Sample Project Answer

@专家:如果您真的是一位优秀的专家,那么请提供帮助,objective 而不是试图告诉人们您是专家并且您知道其他人不知道的事情。此外,给出一些没有真正帮助和主观的建议会让提出问题的人感到沮丧。

郑重声明:我不在乎否决票,我在乎的是有人愿意提供帮助和我获得的知识。

WndProc 代码:

LRESULT CALLBACK MDIAppWndProc(
    HWND hwnd,        // handle to window
    UINT uMsg,        // message identifier
    WPARAM wParam,    // first message parameter
    LPARAM lParam)    // second message parameter
{
    WNDPROC wpOrigMDIAppWndProc = (WNDPROC)GetWindowLongPtr(hwnd, GWL_USERDATA);

    if (wpOrigMDIAppWndProc == NULL)
    {
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }

    switch (uMsg)
    {

    case WM_ACTIVATE:
    case WM_SETFOCUS:
        return 0;

    case WM_CLOSE:
        SetWindowLong(hwnd, GWL_WNDPROC, (LONG)wpOrigMDIAppWndProc);
        PostMessage(hwnd, WM_CLOSE, 0, 0);
        return 0;

    default:
        return CallWindowProc(wpOrigMDIAppWndProc, hwnd, uMsg, wParam, lParam);
    }
    return 0;
}

分离代码:

HWND MDIHwnd = pMainFrame->m_hWndMDIClient;
HWND mdiChildHwnd = GetWindow(MDIHwnd, GW_CHILD);

unsigned int style = GetWindowLongPtr(mdiChildHwnd, GWL_STYLE);
style = (style & (~WS_CHILD) | WS_POPUP);
SetWindowLongPtr(mdiChildHwnd, GWL_STYLE, style);

WaitForInputIdle(mdiChildHwnd, INFINITE);
SetParent(mdiChildHwnd, NULL);

WaitForInputIdle(mdiChildHwnd, INFINITE);
SetWindowLongPtr(mdiChildHwnd, GWLP_HWNDPARENT, (long)MDIHwnd);

HWND MDIAppHwnd = GetAncestor(MDIHwnd, GA_ROOT);

WNDPROC wpOrigMDIAppWndProc = (WNDPROC)SetWindowLong(MDIAppHwnd, GWL_WNDPROC, (LONG)MDIAppWndProc);
SetWindowLongPtr(MDIAppHwnd, GWL_USERDATA, (LONG)wpOrigMDIAppWndProc);