Winapi Can';将MDI子对象从MDI客户端区域中分离时,不要单击控件/菜单

Winapi Can';将MDI子对象从MDI客户端区域中分离时,不要单击控件/菜单,winapi,visual-c++,subclassing,Winapi,Visual C++,Subclassing,整个样本项目可在此处找到: 正常MDI子级: 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(md

整个样本项目可在此处找到:

正常MDI子级:

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

MDI子级已从MDI客户端区域中分离:

问题是在分离MDI子对象后,我无法再单击菜单/控件

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

欢迎任何想法/其他方法

我用于分离MDI子级的代码:

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

这里的一些专家说这是不可能的,我找到了解决办法。
经验教训:当有人说这是不可能的,这意味着这对他们来说是不可能的,而不是你

整个样本项目可在此处找到:

@专家:如果你真的是一个好专家,那么就要乐于助人、客观,而不是试图告诉别人你是专家,你知道别人不知道的事情。此外,给出一些没有真正帮助的建议,而且过于主观,这对提出问题的人来说真的很沮丧。

记录在案:我不在乎被否决的选票,我在乎的是有人愿意帮助我,以及我得到的知识

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

SetWindowLongPtr(mdiChildHwnd,GWL_样式,0x94CF0000)
-您真的希望我们破译您使用的魔法数字吗?如果你需要帮助,你需要让你的代码更容易理解,而不是更难理解。而且,
WaitForInputIdle
并不像您想象的那样。你在某种程度上使用它,这会使物体抓住空气。编程不是猜对的艺术。这是不受支持的。MDI子级不能从主客户端区域“分离”。MDI子窗口是一种特殊类型的窗口。正确的解决方案是不使用MDI。自从32位Windows推出以来,这已经过时了。@CodyGray我别无选择。MDI是一个现有的应用程序,我没有源代码。所附的样本项目仅用于测试。关键是我需要将MDI子对象从MDI中分离出来client@IInspectable:代码已编辑。WaitForInputdle存在,因为如果没有它,如果我尝试分离MDI子级,某些MDI应用程序将崩溃。是的,我不知道它到底是做什么的,但它满足了我的需求。如果你知道,那么在这里解释一下,这样任何人都可以从中受益。在这个宇宙中没有任何可以想象的理由在窗口句柄上调用
WaitForInputIdle
。它什么也不做。完全这就是返回值试图告诉您的内容。你知道,真正令人沮丧的是,有人告诉你三次,你对
WaitForInputIdle
的调用是错误的,没有做任何事情。而且它根本不适合你。停止编写代码。停止发布答案。你也应该停止问问题。无论如何,这不是一个受支持的场景。你的技术为你所同情的专家所熟知。他们也知道你完全忽略的故障模式。祝你的客户好运,他们会抱怨你的代码出现随机死锁。哈哈,现在你说所有的专家都知道你所知道的。好极了,我爱你,专家!!现在,如果你能告诉我失败模式,那么你是一个很好的专家。如果你不能,我不知道你是什么。好啊如果你不能停止用你的评论打扰我,你这个专家!!你的评论是如此令人沮丧,就像你是一个非常好的专家,但实际上它是如此主观。我证明自己,第三方dll子类化了MDI应用程序,也可以在这里复制解决方案。如果您不能向我显示故障模式,请停止!!这也是我对你最后的评论!