Direct creation of CWnd Object
-
Hi, I have a MDI project but I wanted to display a window with some info that is not based on my document. I was able to do this and to draw in the window. If I move the window the drawing remains but if I resize it the drawing disappears. I thought the CS_VREDRAW | CS_HREDRAW would take care of this. Also, I don't get the minimize, maximize, close buttons. I'm guessing there are some style conflicts. Here is the code, it is executed based on a menu selection. Thanks
CMDIChildWnd * pChild =
((CMDIFrameWnd*)(AfxGetApp()->m_pMainWnd))->MDIGetActive();
CMainFrame* pMainFrm = GetMainFrame();
LPCTSTR ClassName = (LPCTSTR)AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW,::LoadCursor(NULL, IDC_ARROW),(HBRUSH) ::GetStockObject(WHITE_BRUSH),::LoadIcon(NULL, IDI_APPLICATION));
pMainFrm->Wnd.CreateEx(0, ClassName, "Win",WS_CAPTION | WS_VISIBLE | WS_SIZEBOX | WS_MINIMIZEBOX | WS_MAXIMIZEBOX ,
0, 0, 600,800, pChild->m_hWnd, (HMENU)NULL);
pMainFrm->Wnd.ShowWindow(SW_SHOWNORMAL);
pMainFrm->Wnd.CenterWindow();CPaintDC dc(CWnd::FromHandle(pMainFrm->Wnd));
-
Hi, I have a MDI project but I wanted to display a window with some info that is not based on my document. I was able to do this and to draw in the window. If I move the window the drawing remains but if I resize it the drawing disappears. I thought the CS_VREDRAW | CS_HREDRAW would take care of this. Also, I don't get the minimize, maximize, close buttons. I'm guessing there are some style conflicts. Here is the code, it is executed based on a menu selection. Thanks
CMDIChildWnd * pChild =
((CMDIFrameWnd*)(AfxGetApp()->m_pMainWnd))->MDIGetActive();
CMainFrame* pMainFrm = GetMainFrame();
LPCTSTR ClassName = (LPCTSTR)AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW,::LoadCursor(NULL, IDC_ARROW),(HBRUSH) ::GetStockObject(WHITE_BRUSH),::LoadIcon(NULL, IDI_APPLICATION));
pMainFrm->Wnd.CreateEx(0, ClassName, "Win",WS_CAPTION | WS_VISIBLE | WS_SIZEBOX | WS_MINIMIZEBOX | WS_MAXIMIZEBOX ,
0, 0, 600,800, pChild->m_hWnd, (HMENU)NULL);
pMainFrm->Wnd.ShowWindow(SW_SHOWNORMAL);
pMainFrm->Wnd.CenterWindow();CPaintDC dc(CWnd::FromHandle(pMainFrm->Wnd));
al2500 wrote:
I don't get the minimize, maximize, close buttons. I'm guessing there are some style conflicts.
Frm MSDN article [Window Styles (Windows)](https://msdn.microsoft.com/en-us/library/windows/desktop/ms632600(v=vs.85).aspx):
Quote:
WS_MAXIMIZEBOX 0x00010000L The window has a maximize button. Cannot be combined with the WS_EX_CONTEXTHELP style. The WS_SYSMENU style must also be specified.
-
Hi, I have a MDI project but I wanted to display a window with some info that is not based on my document. I was able to do this and to draw in the window. If I move the window the drawing remains but if I resize it the drawing disappears. I thought the CS_VREDRAW | CS_HREDRAW would take care of this. Also, I don't get the minimize, maximize, close buttons. I'm guessing there are some style conflicts. Here is the code, it is executed based on a menu selection. Thanks
CMDIChildWnd * pChild =
((CMDIFrameWnd*)(AfxGetApp()->m_pMainWnd))->MDIGetActive();
CMainFrame* pMainFrm = GetMainFrame();
LPCTSTR ClassName = (LPCTSTR)AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW,::LoadCursor(NULL, IDC_ARROW),(HBRUSH) ::GetStockObject(WHITE_BRUSH),::LoadIcon(NULL, IDI_APPLICATION));
pMainFrm->Wnd.CreateEx(0, ClassName, "Win",WS_CAPTION | WS_VISIBLE | WS_SIZEBOX | WS_MINIMIZEBOX | WS_MAXIMIZEBOX ,
0, 0, 600,800, pChild->m_hWnd, (HMENU)NULL);
pMainFrm->Wnd.ShowWindow(SW_SHOWNORMAL);
pMainFrm->Wnd.CenterWindow();CPaintDC dc(CWnd::FromHandle(pMainFrm->Wnd));
al2500 wrote:
if I resize it the drawing disappears. I thought the CS_VREDRAW | CS_HREDRAW would take care of this.
If you set these styles then WM_PAINT message will be sent to it after this window has been resized. Do you handle the WM_PAINT message in this class? Also see [Redrawing the Entire Client Area (Windows)](https://msdn.microsoft.com/en-us/library/windows/desktop/dd162910(v=vs.85).aspx)
-
al2500 wrote:
if I resize it the drawing disappears. I thought the CS_VREDRAW | CS_HREDRAW would take care of this.
If you set these styles then WM_PAINT message will be sent to it after this window has been resized. Do you handle the WM_PAINT message in this class? Also see [Redrawing the Entire Client Area (Windows)](https://msdn.microsoft.com/en-us/library/windows/desktop/dd162910(v=vs.85).aspx)
That is not the problem the MDI classes deal with this automatically. Unfortunately I only know the raw Windows API not the MFC extension of this but I am sure someone using MFC a lot will know. The basics are there is an invisible transparent client area in an MDI class and it is that which is responsible for all the default message behaviour including moving the min/max icons to the frame of the parent window. The MDI child window is supposed to call DefMDIChildProc rather than DefWindowProc as it's default message handler. If you look at a sample when for example I run OpenGL sessions in each MDI the redraws are automatically dealt with. Native Win32 API OpenGL Tutorial - Part 2[^] The MFC base class needs to setup the MDIClientArea and change the handlers of the children and that is all that is missing. The process and setup MFC needs to do that is all you need to know and I am sure someone will tell him. He told you the min/max icons aren't moving to the parent properly so it is definitely the message handler nothing to do with the paint.
In vino veritas
-
That is not the problem the MDI classes deal with this automatically. Unfortunately I only know the raw Windows API not the MFC extension of this but I am sure someone using MFC a lot will know. The basics are there is an invisible transparent client area in an MDI class and it is that which is responsible for all the default message behaviour including moving the min/max icons to the frame of the parent window. The MDI child window is supposed to call DefMDIChildProc rather than DefWindowProc as it's default message handler. If you look at a sample when for example I run OpenGL sessions in each MDI the redraws are automatically dealt with. Native Win32 API OpenGL Tutorial - Part 2[^] The MFC base class needs to setup the MDIClientArea and change the handlers of the children and that is all that is missing. The process and setup MFC needs to do that is all you need to know and I am sure someone will tell him. He told you the min/max icons aren't moving to the parent properly so it is definitely the message handler nothing to do with the paint.
In vino veritas
leon de boer wrote:
He told you the min/max icons aren't moving to the parent properly so it is definitely the message handler nothing to do with the paint.
Didn't you read my previous reply? PS: Please, note what he pointed out: "I don't get the minimize, maximize, close buttons. I'm guessing there are some style conflicts."
-
leon de boer wrote:
He told you the min/max icons aren't moving to the parent properly so it is definitely the message handler nothing to do with the paint.
Didn't you read my previous reply? PS: Please, note what he pointed out: "I don't get the minimize, maximize, close buttons. I'm guessing there are some style conflicts."
I left it because I understand you have linked the MSDN Page but that is incorrect which I suspected and I tried it :-) Download my code and change the MDI child create removing the WS_OVERLAPPEDWINDOW and replace with his flags
if (Child == 0){
Child = CreateWindowEx(WS_EX_MDICHILD,
MDICHILD_CLASSNAME, _T("OpenGL MDI Client"),
WS_CHILD | WS_VISIBLE | WS_CAPTION | WS_SIZEBOX | WS_MINIMIZEBOX | WS_MAXIMIZEBOX/*WS_OVERLAPPEDWINDOW*/,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
AppMDIClient, NULL, GetModuleHandle(0),
NULL); // Create the MDI Child
}Code still works perfectly as I suspected from my playing around with MDI because I know what all the flags do. The statement was possibly true historically but current API does not respect that documentation. So you are technically correct from documentation and he should just use WS_OVERLAPPEDWINDOW but his flags work regardless and isn't the problem. I am not posting hypothetical I physically checked it because I have working MDI samples and worked thru this stuff. For the record the current windows API seems to use WS_SYSMENU as a flag to engage the keyboard accelerator keystrokes to the MDI child window. That is all I can find that it does. The current documentation says it controls the "system menu box" which doesn't even exist anymore (all that functionality is under the top left title icon and it ignores the flag). So the MSDN documentation needs a little update. I can imagine some poor new user going what is this "system menu box" they are talking about.
In vino veritas
-
I left it because I understand you have linked the MSDN Page but that is incorrect which I suspected and I tried it :-) Download my code and change the MDI child create removing the WS_OVERLAPPEDWINDOW and replace with his flags
if (Child == 0){
Child = CreateWindowEx(WS_EX_MDICHILD,
MDICHILD_CLASSNAME, _T("OpenGL MDI Client"),
WS_CHILD | WS_VISIBLE | WS_CAPTION | WS_SIZEBOX | WS_MINIMIZEBOX | WS_MAXIMIZEBOX/*WS_OVERLAPPEDWINDOW*/,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
AppMDIClient, NULL, GetModuleHandle(0),
NULL); // Create the MDI Child
}Code still works perfectly as I suspected from my playing around with MDI because I know what all the flags do. The statement was possibly true historically but current API does not respect that documentation. So you are technically correct from documentation and he should just use WS_OVERLAPPEDWINDOW but his flags work regardless and isn't the problem. I am not posting hypothetical I physically checked it because I have working MDI samples and worked thru this stuff. For the record the current windows API seems to use WS_SYSMENU as a flag to engage the keyboard accelerator keystrokes to the MDI child window. That is all I can find that it does. The current documentation says it controls the "system menu box" which doesn't even exist anymore (all that functionality is under the top left title icon and it ignores the flag). So the MSDN documentation needs a little update. I can imagine some poor new user going what is this "system menu box" they are talking about.
In vino veritas
Thanks all, I added the WS_SYSMENU and the min, max, close buttons showed up. I also realized that simply using the CS_VEDRAW, CS_HEDRAW does not enable redrawing during window resizing because there is no code to redraw the window and as was stated I need to respond to the WM_PAINT message. For now I can just use a fixed size window but this makes me wonder how CWnd direct creation with WM_PAINT support is done. One of my many books made the suggestion that the CWnd MyWnd object be declared in the CMainFrame so that when my code object that paints the window gets destroyed MFC still can communicate with the window. However they did not address how to implement the WM_PAINT. Is the solution to not allow the code object that does the window painting to exit (and thus is destroyed) until the window is closed? And if so any hints on how this would be done?
-
Thanks all, I added the WS_SYSMENU and the min, max, close buttons showed up. I also realized that simply using the CS_VEDRAW, CS_HEDRAW does not enable redrawing during window resizing because there is no code to redraw the window and as was stated I need to respond to the WM_PAINT message. For now I can just use a fixed size window but this makes me wonder how CWnd direct creation with WM_PAINT support is done. One of my many books made the suggestion that the CWnd MyWnd object be declared in the CMainFrame so that when my code object that paints the window gets destroyed MFC still can communicate with the window. However they did not address how to implement the WM_PAINT. Is the solution to not allow the code object that does the window painting to exit (and thus is destroyed) until the window is closed? And if so any hints on how this would be done?
This is why I dislike MFC it mystifies what is actually a simple process. On the windows API itself there is a visibility flag it goes under the name WS_VISIBLE and it tells windows whether to draw a window or not. So a window can exist and even be position on screen but not be visible. There are a number of invisible windows actually at play on the desktop of Windows itself. A hint is what do you think the desktop icons are sitting in. The rule goes if you create a new window which is visible and it is inserted into a parent that is visible, the standard windows system handlers will issue an initial WM_PAINT message. So it is the act of creating the window with a visible parent that for most windows makes it visible. Windows doesn't care about it being a frame or a window it simply cares what the WS_VISIBLE flag of a child and it's parent. So you can create an invisible window easy as hell just don't set the WS_VISIBLE flag (try it on your window). Then you will need to use something like the API call ShowWindow to change it to visible. ShowWindow function (Windows)[^] That call can also be used to make a visible window go invisible and yes the window will still be there just not visible :-) You can also upset visibility by fouling up the message handler so it no longer does the default behaviour correctly and you always know that because you will find your paint behaviour is no longer as it should be. So being visible has absolutely nothing to do with a window existing and invisible windows still exists to the message handlers and you can send message to invisible windows. An invisible window is simply a window that doesn't draw because the visibility flag is wrong or the handler stops it. The only way to destroy a window is via DestroyWindow function (Windows)[^] All the close icons, ALT F4 etc lead to that call if they destroy the window (with the exception an application main window .. it is special and posts a quit message). So a big difference between a window not being visible and a window being destroyed and don't ever think the two things are