-4

Whole sample project can be found here: Sample project

Normal MDI child:

enter image description here

MDI child is detached out of MDI client area:

enter image description here

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);
MarkJoy
  • 55
  • 6
  • 1
    `SetWindowLongPtr(mdiChildHwnd, GWL_STYLE, 0x94CF0000)` - do you seriously expect us to decipher your use of magic numbers? If you need help, you need to make it **easy** to follow your code, not harder. Also, `WaitForInputIdle` doesn't do what you think it does. And you are using it in a way, that causes the [documentation](https://msdn.microsoft.com/en-us/library/windows/desktop/ms687022.aspx) to grasp for air. Programming is **not** the art of guessing right. – IInspectable May 08 '17 at 15:06
  • This is not supported. An MDI child ***cannot*** be "detached" from the main client area. MDI children are a special type of window. The correct solution is not to use MDI. That has been obsolete since the introduction of 32-bit Windows. – Cody Gray - on strike May 08 '17 at 15:06
  • @CodyGray I don't have a choice. The MDI is an existing app which I don't have the source code. The attached sample project is for testing only. The point is I need to detach MDI child out of MDI client – MarkJoy May 08 '17 at 15:13
  • @IInspectable: code is edited. WaitForInputIdle is there because without it, some MDI apps will crash if I try to detach MDI child. Yeah, I don't know what it does exactly, but it made what I want. If you know, then explain it here so anyone can benefit from it. – MarkJoy May 08 '17 at 15:18
  • 1
    There is no conceivable reason in this universe to call `WaitForInputIdle` on a window handle. It does **nothing**. At all. That's what the return value is trying to tell you. The one you are gratuitously ignoring. – IInspectable May 08 '17 at 21:53
  • Boy oh boy. Mark, I understand you might be frustrated at people telling you that (A) your code is wrong, and (B) what you're trying to do is essentially impossible, or at least terrible design, but it does absolutely no good to *attack* those people who are trying to help you. I had left this tab open with a mind to writing a complete answer when I had more time, but you are obviously not interested in expert feedback, so I won't bother. And yes, I downvoted this question to help save others from wasting their time with it. Best of luck to you. – Cody Gray - on strike May 09 '17 at 09:55

1 Answers1

-1

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);
Community
  • 1
  • 1
MarkJoy
  • 55
  • 6
  • You know, what **really** is frustrating is, that you are being told **three** times, that your call to `WaitForInputIdle` is wrong, and doesn't do anything. And it simply doesn't sink in with you. Stop writing code. Stop posting answers. And you should probably also stop asking questions as well. Anyway, this is not a supported scenario. Your hack is well known by the experts that you pity. What's also known by them is the failure mode you are completely ignoring. Good luck with your customers that will complain about random deadlocks of your code. – IInspectable May 10 '17 at 19:12
  • haaa now you said all the expert know it as you knew it. bravo, I love you man, EXPERT!! – MarkJoy May 10 '17 at 20:24
  • Now if you can show me the failure mode then you are a good expert. If you can't, I don't know what you are. OK!? If you can't then stop bothering me with your comments, you EXPERT!! Your comment was so frustrating from [this thread](http://stackoverflow.com/questions/43827438/is-there-any-way-to-know-if-a-window-procedure-was-subclassed) like you a a really good EXPERT, but actually it's so subjective. I prove myself that the 3rd party dll subclassed the MDI app and also can reproduce the solution here. If you can't show me the failure mode then STOP!! this is also my last comment to you! – MarkJoy May 10 '17 at 20:31