WM_SHOWWINDOW not called
-
Hi. I have noticed something interesting: in an MDI app, I handled
ON_WM_SHOWWINDOW()
inCChildFrame
, just like this:void CChildFrame::OnShowWindow(BOOL bShow, UINT nStatus)
{
CMDIChildWnd::OnShowWindow(bShow, nStatus);// TODO: Add your message handler code here
TRACE("%d\n", bShow);
}and whenever I create a new childframe (several times), I see the TRACE, so, this message are handled. But, if I maximize the child frame, the next childframes opened are not handle this message at all ... why ? Strange ... once I maximize the childframe, whenever I create the new childframes, this message are not handled (I mean, I don't see any TRACE) ! If I restore the child frame, next child open are handle this message ... why ? Thank for any explanation, words, everything ! But,
-
Hi. I have noticed something interesting: in an MDI app, I handled
ON_WM_SHOWWINDOW()
inCChildFrame
, just like this:void CChildFrame::OnShowWindow(BOOL bShow, UINT nStatus)
{
CMDIChildWnd::OnShowWindow(bShow, nStatus);// TODO: Add your message handler code here
TRACE("%d\n", bShow);
}and whenever I create a new childframe (several times), I see the TRACE, so, this message are handled. But, if I maximize the child frame, the next childframes opened are not handle this message at all ... why ? Strange ... once I maximize the childframe, whenever I create the new childframes, this message are not handled (I mean, I don't see any TRACE) ! If I restore the child frame, next child open are handle this message ... why ? Thank for any explanation, words, everything ! But,
-
-
Thank you ... I wonder how to know for sure when a childframe have been created ... I will do some tests.
Same way as your last question handle the WM_CREATE message of the child window (or WM_MDICREATE of the parent MDICLIENT) and you know when it's created. It's a basic thing if you want to know absolutely about something (without delay) then insert code in that handler instead of trying to determine it from a parent or associated window where the message chain gets involved. It's easier and safer than the alternatives. The other key things with MDI's is children will by default be handled by DefMDIChildProc and be inside an MDIClient window (which is like an invisible window that sits inside an normal window) for them to operate correctly. So basically your app window contains an MDICLient, and the MDICLient contains the MDI children. So be careful the children are not actually children of the APP window as such. If you try to insert an MDIChild directly into a normal window it won't operate correctly they must be in an invisible MDIClient window pane.
In vino veritas
-
Same way as your last question handle the WM_CREATE message of the child window (or WM_MDICREATE of the parent MDICLIENT) and you know when it's created. It's a basic thing if you want to know absolutely about something (without delay) then insert code in that handler instead of trying to determine it from a parent or associated window where the message chain gets involved. It's easier and safer than the alternatives. The other key things with MDI's is children will by default be handled by DefMDIChildProc and be inside an MDIClient window (which is like an invisible window that sits inside an normal window) for them to operate correctly. So basically your app window contains an MDICLient, and the MDICLient contains the MDI children. So be careful the children are not actually children of the APP window as such. If you try to insert an MDIChild directly into a normal window it won't operate correctly they must be in an invisible MDIClient window pane.
In vino veritas
Kindly thank you for your information. Actually I want to setup the window placement which have been saved in
CChildFrame::OnDestroy()
:void CChildFrame::OnDestroy()
{
CMDIChildWnd::OnDestroy();// TODO: Add your message handler code here WINDOWPLACEMENT wp; GetWindowPlacement(&wp); if(wp.showCmd == SW\_SHOWMINIMIZED) wp.showCmd = SW\_SHOWMAXIMIZED; AfxGetApp()->WriteProfileBinary(\_T("Settings"), \_T("WindowPlacementChild"), (LPBYTE)&wp, sizeof(wp));
}
and previously I setup the window placement on first
CChildFrame::OnShowWindow
call:void CChildFrame::OnShowWindow(BOOL bShow, UINT nStatus)
{
CMDIChildWnd::OnShowWindow(bShow, nStatus);// TODO: Add your message handler code here if(bShow && ! IsWindowVisible() && m\_bOnce) { m\_bOnce = FALSE; UINT nBytes = 0; WINDOWPLACEMENT\* lwp; if(AfxGetApp()->GetProfileBinary(\_T("Settings"), \_T("WindowPlacementChild"), (LPBYTE\*)&lwp, &nBytes)) SetWindowPlacement(lwp); delete \[\]lwp; }
}
but I discovered that this handler are not called when the previous child frame open are maximized ... where should be the proper place to set the child frame placement on opening ?
-
Same way as your last question handle the WM_CREATE message of the child window (or WM_MDICREATE of the parent MDICLIENT) and you know when it's created. It's a basic thing if you want to know absolutely about something (without delay) then insert code in that handler instead of trying to determine it from a parent or associated window where the message chain gets involved. It's easier and safer than the alternatives. The other key things with MDI's is children will by default be handled by DefMDIChildProc and be inside an MDIClient window (which is like an invisible window that sits inside an normal window) for them to operate correctly. So basically your app window contains an MDICLient, and the MDICLient contains the MDI children. So be careful the children are not actually children of the APP window as such. If you try to insert an MDIChild directly into a normal window it won't operate correctly they must be in an invisible MDIClient window pane.
In vino veritas
-
"Same way as your last question handle the WM_CREATE message of the child window (or WM_MDICREATE of the parent MDICLIENT) and you know when it's created" You mean on creation of child frame ?
I don't think that WM_CREATE is the right place to set child frame placement:
int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMDIChildWnd::OnCreate(lpCreateStruct) == -1)
return -1;// TODO: Add your specialized creation code here UINT nBytes = 0; WINDOWPLACEMENT\* lwp; if(AfxGetApp()->GetProfileBinary(\_T("Settings"), \_T("WindowPlacementChild"), (LPBYTE\*)&lwp, &nBytes)) SetWindowPlacement(lwp); delete \[\]lwp; return 0;
}
Once as I put here this code, I have not child frame system menu anymore.
-
I don't think that WM_CREATE is the right place to set child frame placement:
int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CMDIChildWnd::OnCreate(lpCreateStruct) == -1)
return -1;// TODO: Add your specialized creation code here UINT nBytes = 0; WINDOWPLACEMENT\* lwp; if(AfxGetApp()->GetProfileBinary(\_T("Settings"), \_T("WindowPlacementChild"), (LPBYTE\*)&lwp, &nBytes)) SetWindowPlacement(lwp); delete \[\]lwp; return 0;
}
Once as I put here this code, I have not child frame system menu anymore.
You are returning zero and exiting ... try breaking and dropping thru to the default handler. I warned you about needing the default handler :-) MFC is always funky with its wrapper around the raw API so it's probably return one or some strange value to continue thru to the default handler. If all you are trying to do is reset the window placement use WM_WINDOWPOSCHANGED it is always called from WM_CREATE anyhow. I have did a sample with a different OPENGL in each MDICHILD here and the handler is in the text discussion even Native Win32 API OpenGL Tutorial - Part 2[^] You can ignore the OpenGL itself but the MDI does everything you wanted, it resize, minimizes, maximizes. tiles, cascade etc and you can see the messages I handled.
In vino veritas
-
"Same way as your last question handle the WM_CREATE message of the child window (or WM_MDICREATE of the parent MDICLIENT) and you know when it's created" You mean on creation of child frame ?
I guess I have found the right place to restore the child frame window placement:
void CChildFrame::ActivateFrame(int nCmdShow)
{
// TODO: Add your specialized code here and/or call the base classCMDIChildWnd::ActivateFrame(nCmdShow); if(! m\_bOnce) return; m\_bOnce = FALSE; UINT nBytes = 0; WINDOWPLACEMENT\* lwp; if(AfxGetApp()->GetProfileBinary(\_T("Settings"), \_T("WindowPlacementChild"), (LPBYTE\*)&lwp, &nBytes)) SetWindowPlacement(lwp); delete \[\]lwp;
}
-
I guess I have found the right place to restore the child frame window placement:
void CChildFrame::ActivateFrame(int nCmdShow)
{
// TODO: Add your specialized code here and/or call the base classCMDIChildWnd::ActivateFrame(nCmdShow); if(! m\_bOnce) return; m\_bOnce = FALSE; UINT nBytes = 0; WINDOWPLACEMENT\* lwp; if(AfxGetApp()->GetProfileBinary(\_T("Settings"), \_T("WindowPlacementChild"), (LPBYTE\*)&lwp, &nBytes)) SetWindowPlacement(lwp); delete \[\]lwp;
}
That should only work for the focused child window. Unless MFC overrides windows and activates each window in Z order. Windows normally when it brings up a group of children will only activate them along the focus chain in non MFC. Its very specific on the API. WM_ACTIVATE message (Windows)[^] Sent to both the window being activated and the window being deactivated. If the windows use the same input queue, the message is sent synchronously, first to the window procedure of the top-level window being deactivated, then to the window procedure of the top-level window being activated. By default each window will call down to it's parent to make sure it is activated in a direct line along the focus chain. You can basically follow the activation chain upwards from the application window and arrive at the focus window which is how keyboard messages etc find there way to the right window. So at no stage should two MDI children be active and the active one generally paints it's frame a different colour and brings itself to top (that is the default behviour). The only other child window that would get a normal windows API message is the one losing the focus chain. However if you had 3 children there would always be one window that would never get an activation message no matter what you did as it will neither be gaining or losing activation/focus chain. I would not expect that behaviour on MFC unless it does it's own thing and does a lot of repainting that is totally not done on actual windows API. Given the weird nature of that call with nCmdShow that is possible, all be it a bit naft and horrible hack. The WM_WINDOWPOSCHANGED I gave you does go to each and every child which is also why they tell you that you probably want to override it WM_WINDOWPOSCHANGED message (Windows)[^] By default, the DefWindowProc function sends the WM_SIZE and WM_MOVE messages to the window. The WM_SIZE and WM_MOVE messages are not sent if an application handles the WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient to perform any
-
That should only work for the focused child window. Unless MFC overrides windows and activates each window in Z order. Windows normally when it brings up a group of children will only activate them along the focus chain in non MFC. Its very specific on the API. WM_ACTIVATE message (Windows)[^] Sent to both the window being activated and the window being deactivated. If the windows use the same input queue, the message is sent synchronously, first to the window procedure of the top-level window being deactivated, then to the window procedure of the top-level window being activated. By default each window will call down to it's parent to make sure it is activated in a direct line along the focus chain. You can basically follow the activation chain upwards from the application window and arrive at the focus window which is how keyboard messages etc find there way to the right window. So at no stage should two MDI children be active and the active one generally paints it's frame a different colour and brings itself to top (that is the default behviour). The only other child window that would get a normal windows API message is the one losing the focus chain. However if you had 3 children there would always be one window that would never get an activation message no matter what you did as it will neither be gaining or losing activation/focus chain. I would not expect that behaviour on MFC unless it does it's own thing and does a lot of repainting that is totally not done on actual windows API. Given the weird nature of that call with nCmdShow that is possible, all be it a bit naft and horrible hack. The WM_WINDOWPOSCHANGED I gave you does go to each and every child which is also why they tell you that you probably want to override it WM_WINDOWPOSCHANGED message (Windows)[^] By default, the DefWindowProc function sends the WM_SIZE and WM_MOVE messages to the window. The WM_SIZE and WM_MOVE messages are not sent if an application handles the WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient to perform any
Thank you for explanation. I have noticed something weird also: I open two child frames. Both of them are maximized. I have following code:
void CChildFrame::OnDestroy()
{
WINDOWPLACEMENT wp;
GetWindowPlacement(&wp);
TRACE("Window state: %d\n", wp.showCmd);CMDIChildWnd::OnDestroy(); // TODO: Add your message handler code here
}
I repeat: both of child frames are maximized. I close one of them: the result of TRACE are
Window state: 1
which mean SW_SHOWNORMAL, not maximized. Then, I close the next child frame opened, the result is:
Window state: 3
which mean that is SW_MAXIMIZED .... although all child frame opened were maximized, the only last one tell me that was maximized ... rest of them tell me that was SSHOWNORMAL ? Why ?
-
Thank you for explanation. I have noticed something weird also: I open two child frames. Both of them are maximized. I have following code:
void CChildFrame::OnDestroy()
{
WINDOWPLACEMENT wp;
GetWindowPlacement(&wp);
TRACE("Window state: %d\n", wp.showCmd);CMDIChildWnd::OnDestroy(); // TODO: Add your message handler code here
}
I repeat: both of child frames are maximized. I close one of them: the result of TRACE are
Window state: 1
which mean SW_SHOWNORMAL, not maximized. Then, I close the next child frame opened, the result is:
Window state: 3
which mean that is SW_MAXIMIZED .... although all child frame opened were maximized, the only last one tell me that was maximized ... rest of them tell me that was SSHOWNORMAL ? Why ?
When you close one child, the focus first shifts to the next child window. So at that point the window is not technically maximized, in that maximized is more than about size it is about focus as well. Think about the pesky icons placed in the parent frame that is the window that is maximized. So technically you can't have two child windows WM_MAXIMIZED you can have two of them maximum size but that isn't the same thing :-)
In vino veritas
-
When you close one child, the focus first shifts to the next child window. So at that point the window is not technically maximized, in that maximized is more than about size it is about focus as well. Think about the pesky icons placed in the parent frame that is the window that is maximized. So technically you can't have two child windows WM_MAXIMIZED you can have two of them maximum size but that isn't the same thing :-)
In vino veritas