MDI子窗口和状态栏C win32 API

时间:2018-07-08 20:34:29

标签: c windows api winapi mdi

选择“ 文件->打开”菜单后,我正在创建MDI子窗口。 在“打开”开关语句中,我具有窗口创建功能

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

在该声明之后,我希望显示子MDI窗口,但是什么也没有发生。窗口句柄hwndChild也不同于NULL,并且错误消息框未显示。

似乎错误在于处理WM_SIZE窗口函数内的WndProc消息。

一种解决方法是

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

代替

return 0;
WndProc末尾

。但是此解决方案与状态栏不兼容,因为它随后消失了。

这是完整的代码:

#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;
}

2 个答案:

答案 0 :(得分:0)

要在MDI框架中处理WM_SIZE,请参见DefFrameProc的文档

  

WM_SIZE
  调整MDI客户端窗口的大小以适合新框架窗口的客户端   区域。如果框架窗口过程将MDI客户端窗口的大小调整为   大小不同,则不应将邮件传递到DefWindowProc   功能。

如果要调整框架客户端的大小,请返回零。如果您不调整大小,请传递到DefWindowProc(而不是DefFrameProc

要创建MDI子窗口,请使用MDICREATESTRUCTSendMessage( ... WM_MDICREATE ... )而不是CreateWindowEx(WS_EX_MDICHILD...

建议解决此程序:
我正在使用略有不同的方法来处理默认值。 IDM_EXIT也应致电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);
}

答案 1 :(得分:0)

我已经解决了在WM_SIZE例程中确定MDI客户区大小的问题。

我正在发布答案,并且不要删除问题,因为它将来可能会帮助其他人解决我的问题。 我放了

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

WndProc的末尾,并添加了用于调整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;

最后,我放了return 0;,因为WndProc不必返回DefFrameProc并自动在整个客户区域以及状态栏上自动调整MDI客户的大小,使其消失

我将完整的更正后的源代码发布在这里:

#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;
}