MDI child window and status bar C win32 API [closed]

一笑奈何 提交于 2019-12-13 07:53:54

问题


I am creating an MDI Child Window after selecting "File -> Open" Menu. In the "Open" switch statement I have the window creation function

HWND hwndChild = CreateWindowEx(WS_EX_MDICHILD, childClass, "MDI child", WS_CLIPCHILDREN, 0, 0, 400, 300, hWndClient, MAKEINTRESOURCE(IDM_FIRSTCHILD), GetModuleHandle(NULL), 0);

After that declaration I expected the child MDI window to show but nothing happens. The window handle hwndChild is also different from NULL and the error MessageBox doesn't show.

It seems that the error is in handling the WM_SIZE message inside the WndProc window function.

One solution is to put

return DefFrameProc(hwnd, hWndClient, msg, wParam, lParam);

instead of

return 0;

at the end of WndProc. But this solution is not compatible with the status bar, as it then disappears.

Here is the complete code:

#include <windows.h>
#include <commctrl.h> //per SBARS_SIZEGRIP e STATUSCLASSNAME

#define IDM_OPEN        100
#define IDM_EXIT        101
#define IDM_ABOUT       102
#define IDC_STATUSBAR   103
#define IDM_ARRANGE     104
#define IDM_CASCADE     105
#define IDM_TILE        106
#define IDM_CLOSEALL    107
#define IDM_CLOSE       108
#define ID_CLIENTWND    109
#define IDM_FIRSTCHILD  5000


const char frameClass[] = "myFrameClass";
const char clientClass[] = "mdiclient"; //funziona solo con "mdiclient"
const char childClass[] = "myChildClass";

HWND hWndStatusBar;
HWND hWndClient;



//STEP 5 Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){
    switch (msg){
        case WM_CREATE:
            //STEP 6: Create Status Bar
            hWndStatusBar = CreateWindowEx(0,STATUSCLASSNAME,NULL,
                                           WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
                                           0, 0, 0, 0,
                                           hwnd,
                                           (HMENU)IDC_STATUSBAR,
                                           (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);

            if(!hWndStatusBar){
                MessageBox(NULL, "Failed To Create The Status Bar", "Error", MB_OK | MB_ICONERROR);
                return 0;
            }
            // Establish the number of partitions or 'parts' the status bar will 
            // have, their actual dimensions will be set in the parent window's 
            // WM_SIZE handler.
            RECT rc;
            GetClientRect(hwnd, &rc);
            int nHalf = rc.right / 2;
            int nParts[4] = { nHalf, nHalf + nHalf / 3, nHalf + nHalf * 2 / 3, -1 };
            SendMessage(hWndStatusBar, SB_SETPARTS, 4, (LPARAM)&nParts);

            //crea la finestra CLIENT
            CLIENTCREATESTRUCT ccs;
            // Assign the 'Window' menu.
            ccs.hWindowMenu = GetSubMenu(GetMenu(hwnd), 1); // uno perchè così la finestra appare nel secondo menu (partendo da zero) ovvero nel menu 'Windows'
            ccs.idFirstChild = IDM_FIRSTCHILD;
            // Create the client window. (quella che contiene i child!!)
            hWndClient = CreateWindowEx(WS_EX_CLIENTEDGE, clientClass,//FUNZIONA SOLO CON "mdiclient"
                                        NULL,
                                        WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
                                        0, 0, 0, 0,
                                        hwnd,(HMENU)ID_CLIENTWND/*GetMenu(hwnd)*/,GetModuleHandle(NULL),&ccs);
            if(hWndClient == NULL) {
                MessageBox(NULL, "Client Window Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
                return 0;
            }
        break;
        case WM_SIZE:
            //resize the parts
            GetClientRect(hwnd, &rc);
            nHalf = rc.right / 2;
            nParts[0] = nHalf; nParts[1] = nHalf + nHalf / 3; nParts[2] = nHalf + nHalf * 2 / 3; nParts[3] = -1;
            SendMessage(hWndStatusBar, SB_SETPARTS, 4, (LPARAM)&nParts);
            //resize the statusbar
            SendMessage(GetDlgItem(hwnd, IDC_STATUSBAR), WM_SIZE,0,0);
        break;
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        case WM_COMMAND:
            if(LOWORD(wParam) == IDM_EXIT) DestroyWindow(hwnd);
            if(LOWORD(wParam) == IDM_ABOUT) MessageBox(hwnd,"ABOUT premuto","ciao",MB_OK);
            if(LOWORD(wParam) == IDM_OPEN){
                //apre il file...

                //TODO

                //crea la finestra CHILD
                HWND hwndChild = CreateWindowEx(WS_EX_MDICHILD,               //extended styles
                      childClass,            //control 'class' name
                      "MDI child",              //control caption
                      WS_CLIPCHILDREN,                      //control style 
                      0,                      //position: left
                      0,                       //position: top
                      400,                     //width
                      300,                    //height
                      hWndClient,                      //parent window handle
                      //control's ID
                      MAKEINTRESOURCE(IDM_FIRSTCHILD),
                      GetModuleHandle(NULL),                        //application instance
                      0);                           //user defined info

                if(hwndChild == NULL){
                    MessageBox(hwnd,"Impossibile creare la finestra Child","Errore",MB_ICONERROR);
                }
            }
        break;
        default:
            //return DefWindowProc(hwnd,msg,wParam,lParam);
            return DefFrameProc(hwnd, hWndClient, msg, wParam, lParam); //per tenere conto delle finestre figlie
    }
    return 0;
}

LRESULT CALLBACK ChildWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
    switch(msg) {       
        case WM_CREATE :
//          LPCREATESTRUCT lpCreateStruct = (LPCREATESTRUCT)lParam;
//          LPMDICREATESTRUCT lpMDICreateStruct = (LPMDICREATESTRUCT)lpCreateStruct->lpCreateParams;
//          FrameParam = lpMDICreateStruct->lParam;
        break;  
        case WM_COMMAND:

        break;  
        /* All other messages (a lot of them) are processed using default procedures */
        default:
            return DefMDIChildProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG msg;



    //STEP 1: Registering Frame Class Window
    wc.cbSize           =   sizeof(WNDCLASSEX);
    wc.style            =   CS_HREDRAW | CS_VREDRAW;;
    wc.lpfnWndProc      =   WndProc;
    wc.cbClsExtra       =   0;
    wc.cbWndExtra       =   0;
    wc.hInstance        =   hInstance;
    wc.hIcon            =   LoadIcon(NULL,IDI_APPLICATION);
    wc.hCursor          =   LoadCursor(NULL,IDC_ARROW);
    wc.hbrBackground    =   (HBRUSH)(COLOR_APPWORKSPACE+1);//(COLOR_WINDOW);
    wc.hIconSm          =   LoadIcon(NULL,IDI_APPLICATION);
    wc.lpszMenuName     =   NULL;
    wc.lpszClassName    =   frameClass;

    if(!RegisterClassEx(&wc)){
        MessageBox(NULL,"Frame Window Registration Failed!","Error!",MB_ICONEXCLAMATION);
        return 0;
    }

    //la classe CLIENT non la devo registrare?

    //STEP 1.2: Registering Child Class Window
    wc.lpfnWndProc      =   (WNDPROC)ChildWndProc;
    wc.hIcon            =   (HICON)LoadImage(0,IDI_APPLICATION,IMAGE_ICON,0,0,LR_SHARED);
    wc.hIconSm          =   LoadImage(hInstance,childClass,IMAGE_ICON,16,16,LR_DEFAULTCOLOR);
    wc.hCursor          =   (HCURSOR)LoadImage(0,IDC_ARROW,IMAGE_CURSOR,0,0,LR_SHARED);
    wc.hbrBackground    =   (HBRUSH)(COLOR_WINDOW+1);//(COLOR_WINDOW);
    wc.lpszMenuName     =   NULL;
    wc.lpszClassName    =   childClass;

    if(!RegisterClassEx(&wc)){
        MessageBox(NULL,"Child Window Registration Failed!","Error!",MB_ICONEXCLAMATION);
        return 0;
    }



    //STEP 2: Creating the Window
    hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,
                          frameClass,
                          "046 - Visualizer",
                          WS_VISIBLE|WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT,CW_USEDEFAULT,600,400,
                          NULL,NULL,hInstance,NULL);

    if(hwnd == NULL){
        MessageBox(NULL,"Frame Window Creation Failed!","Error!",MB_ICONEXCLAMATION);
        return 0;
    }

    ShowWindow(hwnd,nCmdShow);
    UpdateWindow(hwnd);



    //STEP 3: Create Menu

    HMENU hMenu = CreateMenu(); //crea un menu vuoto

    HMENU hSubMenu; //variabile usata per aggiungere sottomenu ti tipo POPUP

    hSubMenu = CreatePopupMenu();
    AppendMenu(hSubMenu,MF_STRING,IDM_OPEN,"&Open");
    AppendMenu(hSubMenu,MF_STRING,IDM_CLOSE,"&Close");
    AppendMenu(hSubMenu, MF_SEPARATOR, 0, NULL);
    AppendMenu(hSubMenu,MF_STRING,IDM_EXIT,"&Exit");
    AppendMenu(hMenu,MF_STRING|MF_POPUP,(UINT)hSubMenu,"&File"); //aggiunge il sottomenu al menu

    hSubMenu = CreatePopupMenu();
    AppendMenu(hSubMenu,MF_STRING,IDM_ARRANGE,"Arrange");
    AppendMenu(hSubMenu,MF_STRING,IDM_CASCADE,"Cascade");
    AppendMenu(hSubMenu,MF_STRING,IDM_TILE,"Tile");
    AppendMenu(hSubMenu,MF_STRING,IDM_CLOSEALL,"Close All");
    AppendMenu(hMenu,MF_STRING|MF_POPUP,(UINT)hSubMenu,"&Windows");

    hSubMenu = CreatePopupMenu();
    AppendMenu(hSubMenu,MF_STRING,IDM_ABOUT,"&About");
    AppendMenu(hMenu,MF_STRING|MF_POPUP,(UINT)hSubMenu,"&Help");

    if(hMenu == NULL){
        MessageBox(NULL,"Menu Creation Failed!","Error!",MB_ICONEXCLAMATION);
        return 0;
    }

    SetMenu(hwnd,hMenu); //setta il menu sulla finestra



    //STEP 4: Message Loop
    while(GetMessage(&msg,NULL,0,0) > 0){
        if(hWndClient && TranslateMDISysAccel(hWndClient,&msg)) continue; //process the predefined MDI specific accelerator keys
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

回答1:


To handle WM_SIZE in MDI frame, see documentation for DefFrameProc

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.

If you are resizing the frame's client are, return zero. If you are not resizing then pass to DefWindowProc (not DefFrameProc)

To create a MDI child window, use MDICREATESTRUCT and SendMessage( ... WM_MDICREATE ... ), instead of CreateWindowEx(WS_EX_MDICHILD...

Suggestion to fix the procedure:
I am using a slightly different method to handle defaults. Also IDM_EXIT should call WM_CLOSE

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{
    static MDICREATESTRUCT mdicreate;
    static HINSTANCE hinstance;
    switch(msg) 
    {
    case WM_CREATE:
    {
        hinstance = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);

        CLIENTCREATESTRUCT ccs = { 0 };
        ccs.hWindowMenu = GetSubMenu(GetMenu(hwnd), 1); 
        ccs.idFirstChild = IDM_FIRSTCHILD;
        hWndClient = CreateWindow("MDICLIENT", "", 
            WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
            0, 0, 0, 0, hwnd, NULL, 0, &ccs);

        CreateWindow(STATUSCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 
            0, 0, 0, 0, hwnd, (HMENU)IDC_STATUSBAR, hinstance, NULL);

        return 0;
    }

    case WM_SIZE:
    {
        RECT rc;
        GetClientRect(hwnd, &rc);
        int nHalf = rc.right / 2;
        int nParts[4];
        nParts[0] = nHalf; 
        nParts[1] = nHalf + nHalf / 3; 
        nParts[2] = nHalf + nHalf * 2 / 3; 
        nParts[3] = -1;
        SendMessage(GetDlgItem(hwnd, IDC_STATUSBAR), SB_SETPARTS, 4, (LPARAM)&nParts);
        SendMessage(GetDlgItem(hwnd, IDC_STATUSBAR), WM_SIZE, 0, 0);

        RECT statusRect;
        GetClientRect(GetDlgItem(hwnd, IDC_STATUSBAR), &statusRect);

        rc.bottom -= statusRect.bottom;
        MoveWindow(hWndClient, 0, 0, rc.right, rc.bottom, TRUE);

        return 0;
    }

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;

    case WM_COMMAND:

        if(LOWORD(wParam) == IDM_EXIT)
        {
            SendMessage(hwnd, WM_CLOSE, 0, 0);
            return 0;
        }

        if(LOWORD(wParam) == IDM_ABOUT) 
            MessageBox(hwnd, "ABOUT premuto", "ciao", MB_OK);

        if(LOWORD(wParam) == IDM_OPEN) 
        {
            mdicreate.szClass = childClass;
            mdicreate.szTitle = "Title";
            mdicreate.hOwner = hinstance;
            mdicreate.x = CW_USEDEFAULT; //change this to a small number
            mdicreate.y = CW_USEDEFAULT;
            mdicreate.cx = CW_USEDEFAULT;
            mdicreate.cy = CW_USEDEFAULT;
            mdicreate.style = 0;
            mdicreate.lParam = 0;
            SendMessage(hWndClient, WM_MDICREATE, 0, (LPARAM)
                 (LPMDICREATESTRUCT)&mdicreate);
        }
        break;
    }

    return DefFrameProc(hwnd, hWndClient, msg, wParam, lParam);
}



回答2:


I have solved sizing the MDI client area in WM_SIZE routine.

I'm posting the answer and don't delete the question because it may help someone else with my problem in future. I have put

return DefFrameProc(hwnd, hWndClient, msg, wParam, lParam);

at the end of WndProc and added the code for resizing MDI client window that calculate also the presence of the status bar:

// get client area of frame window
RECT clientRect;
GetClientRect(hwnd, &clientRect);
int frame_dx = clientRect.right - clientRect.left;
int frame_dy = clientRect.bottom - clientRect.top;
// get client area of status bar
RECT statusRect;
GetClientRect(hWndStatusBar, &statusRect);
int status_dy = statusRect.bottom - statusRect.top;
// position the MDIClient such that it doesn't overlap with status bar
MoveWindow(hWndClient, 0, 0, frame_dx, frame_dy - status_dy, TRUE);
//resize the statusbar
SendMessage(GetDlgItem(hwnd, IDC_STATUSBAR), WM_SIZE,0,0); 
return 0;

At the end I have put return 0; because the WndProc have not to return DefFrameProc and automatically size MDI client over the whole client area, and also over the status bar making it disappear.

I post the whole corrected source code here:

#include <windows.h>
#include <commctrl.h> //per SBARS_SIZEGRIP e STATUSCLASSNAME

#define IDM_OPEN        100
#define IDM_EXIT        101
#define IDM_ABOUT       102
#define IDC_STATUSBAR   103
#define IDM_ARRANGE     104
#define IDM_CASCADE     105
#define IDM_TILE        106
#define IDM_CLOSEALL    107
#define IDM_CLOSE       108
#define ID_CLIENTWND    109
#define IDM_FIRSTCHILD  5000


const char frameClass[] = "myFrameClass";
const char clientClass[] = "mdiclient"; //funziona solo con "mdiclient"
const char childClass[] = "myChildClass";

HWND hWndStatusBar = NULL;
HWND hWndClient = NULL;



//STEP 5 Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){
    switch (msg){
        case WM_CREATE:
        {
            //STEP 6: Create Status Bar
            hWndStatusBar = CreateWindowEx(0,STATUSCLASSNAME,NULL,
                                           WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
                                           0, 0, 0, 0,
                                           hwnd,
                                           (HMENU)IDC_STATUSBAR,
                                           (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);

            if(!hWndStatusBar){
                MessageBox(NULL, "Failed To Create The Status Bar", "Error", MB_OK | MB_ICONERROR);
                return 0;
            }
            // Establish the number of partitions or 'parts' the status bar will 
            // have, their actual dimensions will be set in the parent window's 
            // WM_SIZE handler.
            RECT rc;
            GetClientRect(hwnd, &rc);
            int nHalf = rc.right / 2;
            int nParts[4] = { nHalf, nHalf + nHalf / 3, nHalf + nHalf * 2 / 3, -1 };
            SendMessage(hWndStatusBar, SB_SETPARTS, 4, (LPARAM)&nParts);

            //crea la finestra CLIENT
            CLIENTCREATESTRUCT ccs;
            // Assign the 'Window' menu.
            ccs.hWindowMenu = GetSubMenu(GetMenu(hwnd), 1); // uno perchè così la finestra appare nel secondo menu (partendo da zero) ovvero nel menu 'Windows'
            ccs.idFirstChild = IDM_FIRSTCHILD;
            // Create the client window. (quella che contiene i child!!)
            hWndClient = CreateWindowEx(WS_EX_CLIENTEDGE, clientClass,//FUNZIONA SOLO CON "mdiclient"
                                        NULL,
                                        WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
                                        0, 0, 0, 0,
                                        hwnd,(HMENU)ID_CLIENTWND/*GetMenu(hwnd)*/,GetModuleHandle(NULL),&ccs);
            if(hWndClient == NULL) {
                MessageBox(NULL, "Client Window Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
                return 0;
            }
        break;
        }
        case WM_SIZE:
        {
            //resize the parts
            RECT rc;
            GetClientRect(hwnd, &rc);
            int nHalf = rc.right / 2;
            int nParts[4] = { nHalf, nHalf + nHalf / 3, nHalf + nHalf * 2 / 3, -1 };
            SendMessage(hWndStatusBar, SB_SETPARTS, 4, (LPARAM)&nParts);
            //resize MDI
            // get client area of frame window
            RECT clientRect;
            GetClientRect(hwnd, &clientRect);
            int frame_dx = clientRect.right - clientRect.left;
            int frame_dy = clientRect.bottom - clientRect.top;
            // get client area of status bar
            RECT statusRect;
            GetClientRect(hWndStatusBar, &statusRect);
            int status_dy = statusRect.bottom - statusRect.top;
            // position the MDIClient such that it doesn't overlap with status bar
            MoveWindow(hWndClient, 0, 0, frame_dx, frame_dy - status_dy, TRUE);
            //resize the statusbar
            SendMessage(GetDlgItem(hwnd, IDC_STATUSBAR), WM_SIZE,0,0); 
            return 0; //ritorna zero altrimenti la Frame Window ridisegna il MDI client spalmandolo su tutta la client area andando sopra alla status bar
        }
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        case WM_COMMAND:
            if(LOWORD(wParam) == IDM_EXIT) DestroyWindow(hwnd);
            if(LOWORD(wParam) == IDM_ABOUT) MessageBox(hwnd,"ABOUT premuto","ciao",MB_OK);
            if(LOWORD(wParam) == IDM_OPEN){
                //apre il file...

                //TODO

                //crea la finestra CHILD
//              HWND hwndChild = CreateWindowEx(WS_EX_MDICHILD,               //extended styles
//                      childClass,            //control 'class' name
//                      "MDI child",              //control caption
//                      WS_CLIPCHILDREN|WS_CLIPSIBLINGS,                      //control style 
//                      0,                      //position: left
//                      0,                       //position: top
//                      400,                     //width
//                      300,                    //height
//                      hWndClient,                      //parent window handle
//                      //control's ID
//                      MAKEINTRESOURCE(IDM_FIRSTCHILD),
//                      GetModuleHandle(NULL),                        //application instance
//                      0);                           //user defined info
//              
//                if(hwndChild == NULL){
//                  MessageBox(hwnd,"Impossibile creare la finestra Child","Errore",MB_ICONERROR);
//              }
                //metodo alternativo da StackOverflow
                MDICREATESTRUCT mdicreate = {0};                
                mdicreate.szClass = childClass;
                mdicreate.szTitle = "class_mdichild";
                mdicreate.hOwner = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE); // <- hinstance
                mdicreate.x = CW_USEDEFAULT;
                mdicreate.y = CW_USEDEFAULT;
                mdicreate.cx = CW_USEDEFAULT;
                mdicreate.cy = CW_USEDEFAULT;
                mdicreate.style = 0;
                mdicreate.lParam = 0;
                HWND hwndChild = (HWND)SendMessage(hWndClient, WM_MDICREATE, 0,(LPARAM)(LPMDICREATESTRUCT)&mdicreate);
                if(hwndChild == NULL) {
                    MessageBox(hwnd, "Impossibile creare la finestra Child", "Errore", MB_ICONERROR);
                }
            }
        break;
        default:
            //return DefWindowProc(hwnd,msg,wParam,lParam);
            return DefFrameProc(hwnd, hWndClient, msg, wParam, lParam); //per tenere conto delle finestre figlie
    }
    return DefFrameProc(hwnd, hWndClient, msg, wParam, lParam);
}

LRESULT CALLBACK ChildWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
    switch(msg) {       
        case WM_CREATE :
//          LPCREATESTRUCT lpCreateStruct = (LPCREATESTRUCT)lParam;
//          LPMDICREATESTRUCT lpMDICreateStruct = (LPMDICREATESTRUCT)lpCreateStruct->lpCreateParams;
//          FrameParam = lpMDICreateStruct->lParam;
        break;  
        case WM_COMMAND:

        break;  
        /* All other messages (a lot of them) are processed using default procedures */
        default:
            return DefMDIChildProc(hwnd, msg, wParam, lParam);
    }
    return DefMDIChildProc(hwnd, msg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG msg;



    //STEP 1: Registering Frame Class Window
    wc.cbSize           =   sizeof(WNDCLASSEX);
    wc.style            =   CS_HREDRAW | CS_VREDRAW;;
    wc.lpfnWndProc      =   WndProc;
    wc.cbClsExtra       =   0;
    wc.cbWndExtra       =   0;
    wc.hInstance        =   hInstance;
    wc.hIcon            =   LoadIcon(NULL,IDI_APPLICATION);
    wc.hCursor          =   LoadCursor(NULL,IDC_ARROW);
    wc.hbrBackground    =   (HBRUSH)(COLOR_APPWORKSPACE+1);//(COLOR_WINDOW);
    wc.hIconSm          =   LoadIcon(NULL,IDI_APPLICATION);
    wc.lpszMenuName     =   NULL;
    wc.lpszClassName    =   frameClass;

    if(!RegisterClassEx(&wc)){
        MessageBox(NULL,"Frame Window Registration Failed!","Error!",MB_ICONEXCLAMATION);
        return 0;
    }

    //la classe CLIENT non la devo registrare?

    //STEP 1.2: Registering Child Class Window
    wc.lpfnWndProc      =   (WNDPROC)ChildWndProc;
    wc.hIcon            =   (HICON)LoadImage(0,IDI_APPLICATION,IMAGE_ICON,0,0,LR_SHARED);
    wc.hIconSm          =   LoadImage(hInstance,childClass,IMAGE_ICON,16,16,LR_DEFAULTCOLOR);
    wc.hCursor          =   (HCURSOR)LoadImage(0,IDC_ARROW,IMAGE_CURSOR,0,0,LR_SHARED);
    wc.hbrBackground    =   (HBRUSH)(COLOR_WINDOW+1);//(COLOR_WINDOW);
    wc.lpszMenuName     =   NULL;
    wc.lpszClassName    =   childClass;

    if(!RegisterClassEx(&wc)){
        MessageBox(NULL,"Child Window Registration Failed!","Error!",MB_ICONEXCLAMATION);
        return 0;
    }



    //STEP 2: Creating the Window
    hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,
                          frameClass,
                          "046 - Visualizer",
                          WS_VISIBLE|WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT,CW_USEDEFAULT,600,400,
                          NULL,NULL,hInstance,NULL);

    if(hwnd == NULL){
        MessageBox(NULL,"Frame Window Creation Failed!","Error!",MB_ICONEXCLAMATION);
        return 0;
    }

    ShowWindow(hwnd,nCmdShow);
    UpdateWindow(hwnd);



    //STEP 3: Create Menu

    HMENU hMenu = CreateMenu(); //crea un menu vuoto

    HMENU hSubMenu; //variabile usata per aggiungere sottomenu ti tipo POPUP

    hSubMenu = CreatePopupMenu();
    AppendMenu(hSubMenu,MF_STRING,IDM_OPEN,"&Open");
    AppendMenu(hSubMenu,MF_STRING,IDM_CLOSE,"&Close");
    AppendMenu(hSubMenu, MF_SEPARATOR, 0, NULL);
    AppendMenu(hSubMenu,MF_STRING,IDM_EXIT,"&Exit");
    AppendMenu(hMenu,MF_STRING|MF_POPUP,(UINT)hSubMenu,"&File"); //aggiunge il sottomenu al menu

    hSubMenu = CreatePopupMenu();
    AppendMenu(hSubMenu,MF_STRING,IDM_ARRANGE,"Arrange");
    AppendMenu(hSubMenu,MF_STRING,IDM_CASCADE,"Cascade");
    AppendMenu(hSubMenu,MF_STRING,IDM_TILE,"Tile");
    AppendMenu(hSubMenu,MF_STRING,IDM_CLOSEALL,"Close All");
    AppendMenu(hMenu,MF_STRING|MF_POPUP,(UINT)hSubMenu,"&Windows");

    hSubMenu = CreatePopupMenu();
    AppendMenu(hSubMenu,MF_STRING,IDM_ABOUT,"&About");
    AppendMenu(hMenu,MF_STRING|MF_POPUP,(UINT)hSubMenu,"&Help");

    if(hMenu == NULL){
        MessageBox(NULL,"Menu Creation Failed!","Error!",MB_ICONEXCLAMATION);
        return 0;
    }

    SetMenu(hwnd,hMenu); //setta il menu sulla finestra



    //STEP 4: Message Loop
    while(GetMessage(&msg,NULL,0,0) > 0){
        if(hWndClient && TranslateMDISysAccel(hWndClient,&msg)) continue; //process the predefined MDI specific accelerator keys
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}


来源:https://stackoverflow.com/questions/51235797/mdi-child-window-and-status-bar-c-win32-api

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!