将 MDI 子项从 MDI 客户区中分离出来时,无法单击控件/菜单 [英] Can't click on controls/menu when detach MDI child out of MDI client area

查看:21
本文介绍了将 MDI 子项从 MDI 客户区中分离出来时,无法单击控件/菜单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可以在此处找到整个示例项目:

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);等待输入空闲(mdiChildHwnd,无限);SetParent(mdiChildHwnd, NULL);等待输入空闲(mdiChildHwnd,无限);SetWindowLongPtr(mdiChildHwnd, GWLP_HWNDPARENT, (long)MDIHwnd);

解决方案

这里有专家说不可能,我找到了解决方案.
经验教训:当有人说这不可能时,这意味着只有他们才能做到,而不是你.

可以在此处找到整个示例项目:示例项目答案

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

郑重声明:我不在乎被否决,我在乎的是愿意帮助的人和我获得的知识.

WndProc 代码:

LRESULT 回调 MDIAppWndProc(HWND hwnd,//窗口句柄UINT uMsg,//消息标识符WPARAM wParam,//第一个消息参数LPARAM lParam)//第二个消息参数{WNDPROC wpOrigMDIAppWndProc = (WNDPROC)GetWindowLongPtr(hwnd, GWL_USERDATA);如果(wpOrigMDIAppWndProc == NULL){返回 DefWindowProc(hwnd, uMsg, wParam, lParam);}开关 (uMsg){案例 WM_ACTIVATE:案例 WM_SETFOCUS:返回0;案例 WM_CLOSE:SetWindowLong(hwnd, GWL_WNDPROC, (LONG)wpOrigMDIAppWndProc);PostMessage(hwnd, WM_CLOSE, 0, 0);返回0;默认:返回 CallWindowProc(wpOrigMDIAppWndProc, hwnd, uMsg, wParam, lParam);}返回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);等待输入空闲(mdiChildHwnd,无限);SetParent(mdiChildHwnd, NULL);等待输入空闲(mdiChildHwnd,无限);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);

Whole sample project can be found here: Sample project

Normal MDI child:

MDI child is detached out of MDI client area:

Problem is after MDI child is detached, I am not able to click on menu/controls anymore.

I think one approach is to subclass winproc of MDI app, and then catching the messages and redirect them (like this one). But I dont know where to begin.

Any idea/ other approaches are welcome!

The code I used to detach 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);

解决方案

Some experts here said that it's impossible and I found out the solution.
Lesson learnt: when someone said it's impossible which mean that's only impossible to them not you.

Whole sample project can be found here: Sample Project Answer

@Experts: if you are really an good expert then be helpful and objective rather than trying to telling people that you are an expert and you know things that other people don't know. Moreover, giving out some advice that's not really helping and being subjective are really frustrating to people who asking. For reference

For the record: I don't care about the downvote, what I care is someone willing to help and knowledge that I get.

WndProc Code:

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

Detaching code:

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

这篇关于将 MDI 子项从 MDI 客户区中分离出来时,无法单击控件/菜单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆