问题描述
我在选择"文件 - >打开"菜单后,我正在创建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不同,并且错误消息框不会显示.
似乎错误是在WndProc窗口函数内处理WM_SIZE消息.
一个解决方案是放入
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; }
推荐答案
要在MDI帧中处理WM_SIZE,请参阅 DefFrameProc
WM_SIZE
调整MDI客户端窗口的大小以适合新帧窗口的客户端 区域.如果框架窗口过程将MDI客户端窗口大小为a 不同的大小,它不应该将消息传递给DefWindowProc 功能.
如果要调整帧客户端的大小,则返回零.如果您未调整大小,则传递到DefWindowProc(不是DefFrameProc)
要创建MDI子窗口,请使用 MDICREATESTRUCT 和SendMessage( ... WM_MDICREATE ... ),而不是CreateWindowEx(WS_EX_MDICHILD...
建议修复程序:
我正在使用略有不同的方法来处理默认值.还应呼叫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); }
其他推荐答案
我已经解决了在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; }
问题描述
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; }
推荐答案
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); }
其他推荐答案
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; }