none
child window using Win32 API

    Question

  • How can i create a simple blank child window when a key was pressed? any good latest book on win32 available?
    Saturday, October 03, 2009 4:35 PM

Answers

  • Ok, but did you return to create the client window as

    hwndClient = CreateWindow (TEXT ("MDICLIENT"), NULL,
                                         WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,  
                                         0, 0, 0, 0, hwnd, (HMENU) 1, hInst,
                                         (PSTR) &clientcreate) ;


    One other thing I noticed in your code, clientcreate.hWindowMenu should be NULL, since you don't have a menu in your MDI application window.

    • Marked as answer by Wesley Yao Monday, October 12, 2009 3:43 AM
    Saturday, October 03, 2009 6:52 PM
  • For sure, you've got to call DefFrameProc() for default message processing in the Frame Window.

    The reason why you don't receive the WM_KEYDOWN, is due to the fact that the Frame Window doesn't have the focus anymore, when you process this message. The client window already has the focus at that point.

    The best approach to create an MDI child window is through a menu, to avoid this problem !

    • Marked as answer by Wesley Yao Monday, October 12, 2009 3:43 AM
    Saturday, October 03, 2009 8:52 PM
  • The reason it isn't working is simple.

    As Belloc pointed out earlier.

    case WM_CREATE:

             clientcreate.hWindowMenu  = NULL ;
             clientcreate.idFirstChild = 50000 ;
             
             hwndClient = CreateWindowW (TEXT ("MDICLIENT"), NULL,
                                         WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,  
                                         0, 0, 0, 0, hwnd, (HMENU) 1, hInst,
                                         (PSTR) &clientcreate) ;
              return 0 ;

    This is where the problem is, you are creating the MDI client with no size what so ever.

    Change it to

    case WM_CREATE:
             {
             RECT rcFrame;
             clientcreate.hWindowMenu  = NULL ;
             clientcreate.idFirstChild = 50000 ;
             GetClientRect(hwnd, &rcFrame);
             hwndClient = CreateWindowW (TEXT ("MDICLIENT"), NULL,
                                         WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,   
                                         rcFrame.left, rcFrame.top, rcFrame.right, rcFrame.bottom, hwnd, (HMENU) 1, hInst,
                                         (PSTR) &clientcreate) ;
            }
              return 0 ;

    and make sure that you call DefFrameProc at the end and then make sure that the WM_KEYDOWN message gets through from the client to the frame then you will be ok.

    But it would be better if you created the child through some other means, like a menu. The reason why this happens is that the DefFrameProc routes the WM_KEYDOWN messages to the current active child window (if this doesn't exist then it will just vanish), but if you want to check out that things are ok then put your child window creation code into the WM_CREATE above right at the end and you will be able to see it work.
    Visit my (not very good) blog at http://c2kblog.blogspot.com/
    • Edited by Crescens2k Saturday, October 03, 2009 9:14 PM Added Stuff
    • Marked as answer by Wesley Yao Monday, October 12, 2009 3:43 AM
    Saturday, October 03, 2009 9:08 PM
  • Then you use Accelerators and make sure to call TranslateMDISysAccel (http://msdn.microsoft.com/en-us/library/ms644926(VS.85).aspx) and TranslateAccelerator (http://msdn.microsoft.com/en-us/library/ms646373(VS.85).aspx) in your message pump.
    You need to set up your accelerator table first though, so you should read through the section in the MSDN (http://msdn.microsoft.com/en-us/library/ms645526(VS.85).aspx).

    The way accelerators work is that it takes WM_KEYDOWN and then translates it into a WM_COMMAND then sends it to your main window. So you will need a WM_COMMAND message handler in there for that.
    Visit my (not very good) blog at http://c2kblog.blogspot.com/
    • Edited by Crescens2k Saturday, October 03, 2009 9:43 PM
    • Marked as answer by Wesley Yao Monday, October 12, 2009 3:43 AM
    Saturday, October 03, 2009 9:41 PM
  • Point 1 has a direct effect on one of the problems mentioned in the thread.
    When creating a child window using CW_USEDEFAULT for the width and height, the size given in the clients CreateWindow call does have side effects.

    If called with CreateWindow("MDICLIENT", ..., 0, 0, 0, 0, ...); then it defaults to creating children with no client area.

    http://i158.photobucket.com/albums/t100/crescens2k/Untitled-1-1.png

    If called with proper sizes

    GetClientRect(hwnd, &rcCli);
    CreateWindow("MDICLIENT", ..., rcCli.left, rcCli.top, rcCli.right, rcCli.bottom, ...);

    Then it will give the children a client rect which is scaled to the MDI client window.

    http://i158.photobucket.com/albums/t100/crescens2k/Untitled-2-1.png

    Since one of the problems was the size of the child windows then I think this is relevant to the problem.
    Visit my (not very good) blog at http://c2kblog.blogspot.com/
    • Marked as answer by Wesley Yao Monday, October 12, 2009 3:43 AM
    Sunday, October 04, 2009 2:51 PM

All replies

  • CreateWindow("child", "", WS_CHILD | WS_VISIBLE | WS_BORDER, x, y, widht, height, hParent, CHILD_ID, hInstance, NULL);

    "Windows Programming" by Charles Petzold
    Saturday, October 03, 2009 4:42 PM
  • Hi Belloc, i already have that book but i still can't get it to work, can you please check the win32 code below:

    #include <windows.h>

    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    LRESULT CALLBACK HelloWndProc  (HWND, UINT, WPARAM, LPARAM) ;

    HINSTANCE hInst ;
    static TCHAR szHelloClass[] = TEXT ("HelloClass") ;

    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                        PSTR szCmdLine, int iCmdShow)
    {
         static TCHAR szAppName[] = TEXT ("HelloWin") ;

         HWND         hwnd ;
         MSG          msg ;
         WNDCLASS     wndclass ;

         wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
         wndclass.lpfnWndProc   = WndProc ;
         wndclass.cbClsExtra    = 0 ;
         wndclass.cbWndExtra    = 0 ;
         wndclass.hInstance     = hInstance ;
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
         wndclass.hbrBackground = (HBRUSH) GetStockObject (GRAY_BRUSH) ;
         wndclass.lpszMenuName  = NULL ;
         wndclass.lpszClassName = szAppName ;

         if (!RegisterClass (&wndclass))
         {
              MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                          szAppName, MB_ICONERROR) ;
              return 0 ;
         }

         // Register the Hello child window class
             
         wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
         wndclass.lpfnWndProc   = HelloWndProc ;
         wndclass.cbClsExtra    = 0 ;
         wndclass.cbWndExtra    = sizeof (HANDLE) ;
         wndclass.hInstance     = hInstance ;
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
         wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
         wndclass.lpszMenuName  = NULL ;
         wndclass.lpszClassName = szHelloClass ;
             
         RegisterClass (&wndclass) ;

         hwnd = CreateWindow (szAppName,                  // window class name
                              TEXT ("The Hello Program"), // window caption
                              WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,        // window style
                              CW_USEDEFAULT,              // initial x position
                              CW_USEDEFAULT,              // initial y position
                              CW_USEDEFAULT,              // initial x size
                              CW_USEDEFAULT,              // initial y size
                              NULL,                       // parent window handle
                              NULL,                       // window menu handle
                              hInstance,                  // program instance handle
                              NULL) ;                     // creation parameters
        
         ShowWindow (hwnd, iCmdShow) ;
         UpdateWindow (hwnd) ;
        
         while (GetMessage (&msg, NULL, 0, 0))
         {
              TranslateMessage (&msg) ;
              DispatchMessage (&msg) ;
         }
         return int(msg.wParam) ;
    }

    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {  
         static HWND        hwndClient ;
         CLIENTCREATESTRUCT clientcreate ;
         HWND               hwndChild ;
         MDICREATESTRUCT    mdicreate ;


         switch (message)
         {
         case WM_CREATE:
             
             hwndClient = CreateWindow (TEXT ("MDICLIENT"), NULL,
                                         WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,  
                                         0, 0, 0, 0, hwnd, (HMENU) 1, hInst,
                                         (PSTR) &clientcreate) ;
              return 0 ;

         case WM_KEYDOWN: //create the child window here

             mdicreate.szClass = szHelloClass ;
             mdicreate.szTitle = TEXT ("Hello") ;
             mdicreate.hOwner  = hInst ;
             mdicreate.x       = 50 ;
             mdicreate.y       = 40 ;
             mdicreate.cx      = 56 ;
             mdicreate.cy      = 49 ;
             mdicreate.style   = 0 ;
             mdicreate.lParam  = 0 ;
          
             hwndChild = (HWND) SendMessage (hwndClient,
                               WM_MDICREATE, 0,
                               (LPARAM) (LPMDICREATESTRUCT) &mdicreate) ;

                   return 0;

             
         case WM_DESTROY:
              PostQuitMessage (0) ;
              return 0 ;
         }
         return DefWindowProc (hwnd, message, wParam, lParam) ;
    }

    LRESULT CALLBACK HelloWndProc (HWND hwnd, UINT message,
                                   WPARAM wParam, LPARAM lParam)
    {
         switch (message)
         {
         case WM_CREATE:
             
              return 0 ;
             
         case WM_COMMAND:

              return 0 ;
             
         case WM_PAINT:
                   // Paint the window
              return 0 ;

         case WM_CLOSE:
              if (IDOK != MessageBox (hwnd, TEXT ("OK to close window?"),
                                      TEXT ("Hello"),
                                      MB_ICONQUESTION | MB_OKCANCEL))
                   return 0 ;
                  
              break ;   // i.e., call DefMDIChildProc
                  
         case WM_DESTROY:
              return 0 ;
         }
              // Pass unprocessed message to DefMDIChildProc
        
         return DefMDIChildProc (hwnd, message, wParam, lParam) ;
    }
    Saturday, October 03, 2009 5:14 PM
  • That is a long way from a single blank child window you mentined on your first post.

    But anyway, it seems like you have a problem with the MDICLIENT window. It has no dimension. Make it the size of the Frame Window client area.

    Also, you have to supply the idFirstChild member of the CLIENTCREATESTRUCT equal to IDM_FIRSTCHILD, or some other constant integer. I don't think Windows will assume a default for that.

    You didn't initialize your global hInst variable.
    Saturday, October 03, 2009 5:44 PM
  • Thanks Belloc, but when i maximize the MDI child window it disappears, i can't close or minimize it back.
    Saturday, October 03, 2009 6:00 PM
  • Well, there is a huge difference between a child window and an MDI child window.
    If you haven't read it already try looking through the MDI section in the MSDN. It has samples.

    MDI (http://msdn.microsoft.com/en-us/library/ms632591(VS.85).aspx)

    But my bets is that you don't have a working frame window procedure and you didn't call ShowWindow after you created the MDI frame are contributing to it.
    Visit my (not very good) blog at http://c2kblog.blogspot.com/
    Saturday, October 03, 2009 6:03 PM
  • Well, there is a huge difference between a child window and an MDI child window.
    If you haven't read it already try looking through the MDI section in the MSDN. It has samples.

    MDI (http://msdn.microsoft.com/en-us/library/ms632591(VS.85).aspx)

    But my bets is that you don't have a working frame window procedure and you didn't call ShowWindow after you created the MDI frame are contributing to it.
    Visit my (not very good) blog at http://c2kblog.blogspot.com/


    ShowWindow() is there !

    The CreateWindow() in WinMain() creates the Frame Window(). In this regard the OP is correct.

    Saturday, October 03, 2009 6:13 PM
  • Thanks Belloc, but when i maximize the MDI child window it disappears, i can't close or minimize it back.

    Just to see if I'm following you. So you succeeded in creating the child window ?
    Saturday, October 03, 2009 6:15 PM
  • Yes i did, but  there's a problem when i maximize it.
    Saturday, October 03, 2009 6:19 PM
  • I think the problem is where i set the MDIClient window position and size to something like xSize = 50, ySize = 50, w = 500, h = 500 same as that of frame window.
    Saturday, October 03, 2009 6:25 PM
  • I'm not sure. But maybe you need to use CW_USEDEFAULT for the coordinates, and for the width and height, while creating the child window. 
    Saturday, October 03, 2009 6:28 PM
  • Try the following :

    Use (0, 0, 0, 0) as you were using before for the Client Window and use CW_USEDEFAULT for the child window. I think it will work now. 
    Saturday, October 03, 2009 6:37 PM
  • It doesn't work with using CW_USEDEFAULT, but here's a http://i36.tinypic.com/28l4daa.png screenshot when i define position and size. when i move the child window, it seems to hide in client area that i defined xSize = 50, ySize = 50, w = 500, h = 500 same as that of frame window.
    Saturday, October 03, 2009 6:46 PM
  • Ok, but did you return to create the client window as

    hwndClient = CreateWindow (TEXT ("MDICLIENT"), NULL,
                                         WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,  
                                         0, 0, 0, 0, hwnd, (HMENU) 1, hInst,
                                         (PSTR) &clientcreate) ;


    One other thing I noticed in your code, clientcreate.hWindowMenu should be NULL, since you don't have a menu in your MDI application window.

    • Marked as answer by Wesley Yao Monday, October 12, 2009 3:43 AM
    Saturday, October 03, 2009 6:52 PM
  • I'm about to repost the updated code again, but it doesn't work with setting the MDICLIENT window parameters to (0, 0, 0, 0)

    #include <windows.h>

    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
    LRESULT CALLBACK HelloWndProc  (HWND, UINT, WPARAM, LPARAM) ;

    HINSTANCE hInst ;
    static TCHAR szHelloClass[] = TEXT ("HelloClass") ;

    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                        PSTR szCmdLine, int iCmdShow)
    {
         static TCHAR szAppName[] = TEXT ("HelloWin") ;

         HWND         hwnd ;
         MSG          msg ;
         WNDCLASS     wndclass ;

         hInst = hInstance;

         wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
         wndclass.lpfnWndProc   = WndProc ;
         wndclass.cbClsExtra    = 0 ;
         wndclass.cbWndExtra    = 0 ;
         wndclass.hInstance     = hInstance ;
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
         wndclass.hbrBackground = (HBRUSH) GetStockObject (GRAY_BRUSH) ;
         wndclass.lpszMenuName  = NULL ;
         wndclass.lpszClassName = szAppName ;

         if (!RegisterClass (&wndclass))
         {
              MessageBox (NULL, TEXT ("This program requires Windows NT!"),
                          szAppName, MB_ICONERROR) ;
              return 0 ;
         }

         // Register the Hello child window class
             
         wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
         wndclass.lpfnWndProc   = HelloWndProc ;
         wndclass.cbClsExtra    = 0 ;
         wndclass.cbWndExtra    = sizeof (HANDLE) ;
         wndclass.hInstance     = hInstance ;
         wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
         wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
         wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
         wndclass.lpszMenuName  = NULL ;
         wndclass.lpszClassName = szHelloClass ;
             
         RegisterClass (&wndclass) ;

         hwnd = CreateWindow (szAppName,                  // window class name
                              TEXT ("MDI"), // window caption
                              WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,        // window style
                              CW_USEDEFAULT,              // initial x position
                              CW_USEDEFAULT,              // initial y position
                              CW_USEDEFAULT,              // initial x size
                              CW_USEDEFAULT,              // initial y size
                              NULL,                       // parent window handle
                              NULL,                       // window menu handle
                              hInstance,                  // program instance handle
                              NULL) ;                     // creation parameters
        
         ShowWindow (hwnd, iCmdShow) ;
         UpdateWindow (hwnd) ;
        
         while (GetMessage (&msg, NULL, 0, 0))
         {
              TranslateMessage (&msg) ;
              DispatchMessage (&msg) ;
         }
         return int(msg.wParam) ;
    }

    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {  
         static HWND        hwndClient ;
         CLIENTCREATESTRUCT clientcreate ;
         HWND               hwndChild ;
         MDICREATESTRUCT    mdicreate ;


         switch (message)
         {
         case WM_CREATE:

             clientcreate.hWindowMenu  = NULL ;
             clientcreate.idFirstChild = 50000 ;
             
             hwndClient = CreateWindowW (TEXT ("MDICLIENT"), NULL,
                                         WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,  
                                         0, 0, 0, 0, hwnd, (HMENU) 1, hInst,
                                         (PSTR) &clientcreate) ;
              return 0 ;

         case WM_KEYDOWN: //create the child window here

             mdicreate.szClass = szHelloClass ;
             mdicreate.szTitle = TEXT ("Hello") ;
             mdicreate.hOwner  = hInst ;
             mdicreate.x       = CW_USEDEFAULT ;
             mdicreate.y       = CW_USEDEFAULT ;
             mdicreate.cx      = CW_USEDEFAULT ;
             mdicreate.cy      = CW_USEDEFAULT ;
             mdicreate.style   = 0 ;
             mdicreate.lParam  = 0 ;
          
           hwndChild = (HWND) SendMessage (hwndClient,
                               WM_MDICREATE, 0,
                               (LPARAM) (LPMDICREATESTRUCT) &mdicreate) ;

                   return 0;

             
         case WM_DESTROY:
              PostQuitMessage (0) ;
              return 0 ;
         }
         return DefWindowProc (hwnd, message, wParam, lParam) ;
    }

    LRESULT CALLBACK HelloWndProc (HWND hwnd, UINT message,
                                   WPARAM wParam, LPARAM lParam)
    {
         switch (message)
         {
         case WM_CREATE:
             
                   // Save some window handles
              return 0 ;
             
         case WM_COMMAND:

              return 0 ;
             
         case WM_PAINT:
                   // Paint the window
              return 0 ;
                  
         case WM_MDIACTIVATE:
                   // Set the Hello menu if gaining focus
                  
              return 0 ;
                  
         case WM_DESTROY:
              return 0 ;
         }
              // Pass unprocessed message to DefMDIChildProc
        
         return DefMDIChildProc (hwnd, message, wParam, lParam) ;
    }
    Saturday, October 03, 2009 7:03 PM
  • I think I've finally found it : replace DefWindowProc() by DefFrameProc() in WndProc() !

    Saturday, October 03, 2009 7:25 PM
  • return DefFrameProc (hwnd, hwndClient, message, wParam, lParam) ;

    still not working, the MDI child window doesn't appear on keypress.
    Saturday, October 03, 2009 7:39 PM
  • Well, there is a huge difference between a child window and an MDI child window.
    If you haven't read it already try looking through the MDI section in the MSDN. It has samples.

    MDI (http://msdn.microsoft.com/en-us/library/ms632591(VS.85).aspx)

    But my bets is that you don't have a working frame window procedure and you didn't call ShowWindow after you created the MDI frame are contributing to it.
    Visit my (not very good) blog at http://c2kblog.blogspot.com/


    ShowWindow() is there !

    The CreateWindow() in WinMain() creates the Frame Window(). In this regard the OP is correct.

    My bad, I meant the MDI Client and didn't notice the WS_VISIBLE.

    But it makes me wonder if anyone read what I linked to properly.

    Under Using the Multiple Document Interface section it quite clearly states.

    Writing the Frame Window Procedure

    The window procedure for an MDI frame window is similar to that of a non–MDI application's main window. The difference is that a frame window procedure passes all messages it does not handle to the DefFrameProc function rather than to the DefWindowProc function. In addition, the frame window procedure must also pass some messages that it does handle, including those listed in the following table.

    MessageResponse
    WM_COMMAND Activates the MDI child window that the user chooses. This message is sent when the user chooses an MDI child window from the window menu of the MDI frame window. The window identifier accompanying this message identifies the MDI child window to be activated.
    WM_MENUCHAR Opens the window menu of the active MDI child window when the user presses the ALT+ – (minus) key combination.
    WM_SETFOCUS Passes the keyboard focus to the MDI client window, which in turn passes it to the active MDI child window.
    WM_SIZE Resizes the MDI client window to fit in the new frame window's client area. If the frame window procedure sizes the MDI client window to a different size, it should not pass the message to the DefWindowProc function.

    The frame window procedure in Multipad is called MPFrameWndProc. The handling of other messages by MPFrameWndProc is similar to that of non–MDI applications. WM_COMMAND messages in Multipad are handled by the locally defined CommandHandler function. For command messages Multipad does not handle, CommandHandler calls the DefFrameProc function. If Multipad doesn't use DefFrameProc by default, the user can't activate a child window from the window menu, because the WM_COMMAND message sent by clicking the window's menu item would be lost.


    Whats more, you don't even check the return of send message to see if it succeeded and finally, according to the WM_MDICREATE message documentation it only gets the following styles.

    WS_CHILD, WS_CLIPSIBLINGS, WS_CLIPCHILDREN, WS_SYSMENU, WS_CAPTION, WS_THICKFRAME, WS_MINIMIZEBOX, and WS_MAXIMIZEBOX

    So unless you give it WS_VISIBLE you need to call ShowWindow on the MDI child too.
    Visit my (not very good) blog at http://c2kblog.blogspot.com/
    Saturday, October 03, 2009 7:44 PM
  • Include the following on WndProc()

    case WM_SIZE:

    GetClientRect(hwnd, &rect);

    MoveWindow(hwndClient, 0, 0, rect.right, rect.bottom, TRUE);

    return 0;


    Also verify if the  SendMessage (hwndClient, ...) is returning a handle.
    Saturday, October 03, 2009 8:02 PM
  • Well, there is a huge difference between a child window and an MDI child window.
    If you haven't read it already try looking through the MDI section in the MSDN. It has samples.

    MDI (http://msdn.microsoft.com/en-us/library/ms632591(VS.85).aspx)

    But my bets is that you don't have a working frame window procedure and you didn't call ShowWindow after you created the MDI frame are contributing to it.
    Visit my (not very good) blog at http://c2kblog.blogspot.com/


    ShowWindow() is there !

    The CreateWindow() in WinMain() creates the Frame Window(). In this regard the OP is correct.

    My bad, I meant the MDI Client and didn't notice the WS_VISIBLE.

    But it makes me wonder if anyone read what I linked to properly.

    Under Using the Multiple Document Interface section it quite clearly states.

    Writing the Frame Window Procedure

    The window procedure for an MDI frame window is similar to that of a non–MDI application's main window. The difference is that a frame window procedure passes all messages it does not handle to the DefFrameProc function rather than to the DefWindowProc function. In addition, the frame window procedure must also pass some messages that it does handle, including those listed in the following table.

    MessageResponse
    WM_COMMAND Activates the MDI child window that the user chooses. This message is sent when the user chooses an MDI child window from the window menu of the MDI frame window. The window identifier accompanying this message identifies the MDI child window to be activated.
    WM_MENUCHAR Opens the window menu of the active MDI child window when the user presses the ALT+ – (minus) key combination.
    WM_SETFOCUS Passes the keyboard focus to the MDI client window, which in turn passes it to the active MDI child window.
    WM_SIZE Resizes the MDI client window to fit in the new frame window's client area. If the frame window procedure sizes the MDI client window to a different size, it should not pass the message to the DefWindowProc function.

    The frame window procedure in Multipad is called MPFrameWndProc. The handling of other messages by MPFrameWndProc is similar to that of non–MDI applications. WM_COMMAND messages in Multipad are handled by the locally defined CommandHandler function. For command messages Multipad does not handle, CommandHandler calls the DefFrameProc function. If Multipad doesn't use DefFrameProc by default, the user can't activate a child window from the window menu, because the WM_COMMAND message sent by clicking the window's menu item would be lost.


    Whats more, you don't even check the return of send message to see if it succeeded and finally, according to the WM_MDICREATE message documentation it only gets the following styles.

    WS_CHILD, WS_CLIPSIBLINGS, WS_CLIPCHILDREN, WS_SYSMENU, WS_CAPTION, WS_THICKFRAME, WS_MINIMIZEBOX, and WS_MAXIMIZEBOX

    So unless you give it WS_VISIBLE you need to call ShowWindow on the MDI child too.
    Visit my (not very good) blog at http://c2kblog.blogspot.com/

    You don't need the WS_VISIBLE style for an MDI child window and you don't need to call ShowWindow() !
    • Edited by Belloc Saturday, October 03, 2009 8:09 PM typo
    Saturday, October 03, 2009 8:06 PM
  • I added the WM_SIZE in wndproc, now the client area problem is solved, i can move the child window around the parent window but only if i had DefWindowProc() there instead of DefFrameProc() and also It cannot catch WM_KEYDOWN with DefFrameProc().
    Saturday, October 03, 2009 8:32 PM
  • For sure, you've got to call DefFrameProc() for default message processing in the Frame Window.

    The reason why you don't receive the WM_KEYDOWN, is due to the fact that the Frame Window doesn't have the focus anymore, when you process this message. The client window already has the focus at that point.

    The best approach to create an MDI child window is through a menu, to avoid this problem !

    • Marked as answer by Wesley Yao Monday, October 12, 2009 3:43 AM
    Saturday, October 03, 2009 8:52 PM
  • The reason it isn't working is simple.

    As Belloc pointed out earlier.

    case WM_CREATE:

             clientcreate.hWindowMenu  = NULL ;
             clientcreate.idFirstChild = 50000 ;
             
             hwndClient = CreateWindowW (TEXT ("MDICLIENT"), NULL,
                                         WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,  
                                         0, 0, 0, 0, hwnd, (HMENU) 1, hInst,
                                         (PSTR) &clientcreate) ;
              return 0 ;

    This is where the problem is, you are creating the MDI client with no size what so ever.

    Change it to

    case WM_CREATE:
             {
             RECT rcFrame;
             clientcreate.hWindowMenu  = NULL ;
             clientcreate.idFirstChild = 50000 ;
             GetClientRect(hwnd, &rcFrame);
             hwndClient = CreateWindowW (TEXT ("MDICLIENT"), NULL,
                                         WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,   
                                         rcFrame.left, rcFrame.top, rcFrame.right, rcFrame.bottom, hwnd, (HMENU) 1, hInst,
                                         (PSTR) &clientcreate) ;
            }
              return 0 ;

    and make sure that you call DefFrameProc at the end and then make sure that the WM_KEYDOWN message gets through from the client to the frame then you will be ok.

    But it would be better if you created the child through some other means, like a menu. The reason why this happens is that the DefFrameProc routes the WM_KEYDOWN messages to the current active child window (if this doesn't exist then it will just vanish), but if you want to check out that things are ok then put your child window creation code into the WM_CREATE above right at the end and you will be able to see it work.
    Visit my (not very good) blog at http://c2kblog.blogspot.com/
    • Edited by Crescens2k Saturday, October 03, 2009 9:14 PM Added Stuff
    • Marked as answer by Wesley Yao Monday, October 12, 2009 3:43 AM
    Saturday, October 03, 2009 9:08 PM
  • I think i'll have a menu for child window then, but can i create a Form View Dialog with WM_KEYDOWN ?
    Saturday, October 03, 2009 9:12 PM
  • Once you have a menu then you don't need WM_KEYDOWN as input for creating windows.
    You can add menu items and then use the WM_COMMAND to create the Dialog.
    Visit my (not very good) blog at http://c2kblog.blogspot.com/
    Saturday, October 03, 2009 9:16 PM
  • well I just wanted to assign a shortcut key to bring it up.
    Saturday, October 03, 2009 9:24 PM
  • so the keyboard accelerators would do that for MDI windows.
    Saturday, October 03, 2009 9:39 PM
  • Then you use Accelerators and make sure to call TranslateMDISysAccel (http://msdn.microsoft.com/en-us/library/ms644926(VS.85).aspx) and TranslateAccelerator (http://msdn.microsoft.com/en-us/library/ms646373(VS.85).aspx) in your message pump.
    You need to set up your accelerator table first though, so you should read through the section in the MSDN (http://msdn.microsoft.com/en-us/library/ms645526(VS.85).aspx).

    The way accelerators work is that it takes WM_KEYDOWN and then translates it into a WM_COMMAND then sends it to your main window. So you will need a WM_COMMAND message handler in there for that.
    Visit my (not very good) blog at http://c2kblog.blogspot.com/
    • Edited by Crescens2k Saturday, October 03, 2009 9:43 PM
    • Marked as answer by Wesley Yao Monday, October 12, 2009 3:43 AM
    Saturday, October 03, 2009 9:41 PM
  • Thanks.
    Saturday, October 03, 2009 9:43 PM
  • David_21:

    I had to leave just after my last post. There are however two important points in this discussion that should be highlighted:

    1)  The CreateWindow("MDICLIENT", ..., 0, 0, 0, 0, ...) has nothing to do with your problem, as I thought at the start of our discussion. Windows will size the client window automatically according to the Frame Windows' client area.

    2)  The culprit in this case is the keyboard focus. Windows transfers the focus to the client window after its creation. So when you try to process the WM_KEYDOWN message in the frame window to create the MDI child, that message is actually going to the client window. To prove this point, you can subclass the client window, and process the WM_KEYDOWN message there, and your method will work.

    This also explains why the the literature suggests the use of menus to create an MDI child window. Just to avoid this pitfall, for in this case the Frame Window doesn't need the focus to process its menu or an accelerator table.

    3)  You really don't need to process the WM_SIZE, as I suggested above, although it doesn't compromise your code. As a matter of fact, it serves to show that you can deal with a smaller client window if that is desirable.

    Sunday, October 04, 2009 8:44 AM
  • Point 1 has a direct effect on one of the problems mentioned in the thread.
    When creating a child window using CW_USEDEFAULT for the width and height, the size given in the clients CreateWindow call does have side effects.

    If called with CreateWindow("MDICLIENT", ..., 0, 0, 0, 0, ...); then it defaults to creating children with no client area.

    http://i158.photobucket.com/albums/t100/crescens2k/Untitled-1-1.png

    If called with proper sizes

    GetClientRect(hwnd, &rcCli);
    CreateWindow("MDICLIENT", ..., rcCli.left, rcCli.top, rcCli.right, rcCli.bottom, ...);

    Then it will give the children a client rect which is scaled to the MDI client window.

    http://i158.photobucket.com/albums/t100/crescens2k/Untitled-2-1.png

    Since one of the problems was the size of the child windows then I think this is relevant to the problem.
    Visit my (not very good) blog at http://c2kblog.blogspot.com/
    • Marked as answer by Wesley Yao Monday, October 12, 2009 3:43 AM
    Sunday, October 04, 2009 2:51 PM
  • crescens2k:

    I was wrong and you're right. If the CreateWindow() is called for the client window with 0 coordinates, the WM_SIZE message must be processed within the Frame Window to adjust the size of the client window, or the client window should be created as you pointed out above, i.e., by previously calling GetClientRect(hFrame, &rect).

    The reason why I was so vehement in defending my point, is that I was carried by an example given in Petzold's book, which creates the client window with 0 coordinates.

    Please accept my apologies.

    david_21:

    If you adjust the client window size as mentioned above and use an accelerator table to create the child windows, you should be OK.


     

    Sunday, October 04, 2009 8:37 PM