如何使用Win32 API制作多个窗口

我看到大量的教程和文章向我展示了如何制作一个简单的Windows程序,这很棒,但是没有一个告诉我如何制作多个窗口

现在我有创build和绘制分层窗口的工作代码,我可以使用GDI来绘制任何东西,拖动它,甚至使其透明等等。

但是我想要第二个矩形区域,我可以拖动,等等。换句话说,第二个窗口。 可能希望它是一个孩子的窗口。 问题是,我该怎么做呢?

此外,如果有人知道任何良好的资源(在线优先)像Windows API中的窗口pipe理文章或教程,请分享。

如果需要,您可以多次打击CreateWindow()。 WinMain中的消息循环将把事件传递给WinMain创建的所有窗口。 你甚至可以创建两个重叠的窗口,并将第二个窗口的父窗口设置为第一个窗口的句柄。

要创建多个窗口,请重复在创建第一个窗口时创建第二个窗口时所执行的所有步骤。 一个好办法是从第一个窗口复制并粘贴所有的代码。 然后搜索并替换,在第二个窗口中用第一个窗口的唯一名称替换第一个窗口的所有名称。 下面我就是这样做的代码。

最重要的是要注意的是,第二个窗口的windows类应该在代码行“windowclassforwindow2.lpszClassName =”window class2“中有一个唯一的名字,如果没有唯一的名字,windows注册将失败。

  #include <windows.h> LRESULT CALLBACK windowprocessforwindow1(HWND handleforwindow1,UINT message,WPARAM wParam,LPARAM lParam); LRESULT CALLBACK windowprocessforwindow2(HWND handleforwindow2,UINT message,WPARAM wParam,LPARAM lParam); bool window1closed=false; bool window2closed=false; int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR lpCmdLine,int nShowCmd) { bool endprogram=false; //create window 1 WNDCLASSEX windowclassforwindow1; ZeroMemory(&windowclassforwindow1,sizeof(WNDCLASSEX)); windowclassforwindow1.cbClsExtra=NULL; windowclassforwindow1.cbSize=sizeof(WNDCLASSEX); windowclassforwindow1.cbWndExtra=NULL; windowclassforwindow1.hbrBackground=(HBRUSH)COLOR_WINDOW; windowclassforwindow1.hCursor=LoadCursor(NULL,IDC_ARROW); windowclassforwindow1.hIcon=NULL; windowclassforwindow1.hIconSm=NULL; windowclassforwindow1.hInstance=hInst; windowclassforwindow1.lpfnWndProc=(WNDPROC)windowprocessforwindow1; windowclassforwindow1.lpszClassName=L"windowclass 1"; windowclassforwindow1.lpszMenuName=NULL; windowclassforwindow1.style=CS_HREDRAW|CS_VREDRAW; if(!RegisterClassEx(&windowclassforwindow1)) { int nResult=GetLastError(); MessageBox(NULL, L"Window class creation failed", L"Window Class Failed", MB_ICONERROR); } HWND handleforwindow1=CreateWindowEx(NULL, windowclassforwindow1.lpszClassName, L"Parent Window", WS_OVERLAPPEDWINDOW, 200, 150, 640, 480, NULL, NULL, hInst, NULL /* No Window Creation data */ ); if(!handleforwindow1) { int nResult=GetLastError(); MessageBox(NULL, L"Window creation failed", L"Window Creation Failed", MB_ICONERROR); } ShowWindow(handleforwindow1,nShowCmd); // create window 2 WNDCLASSEX windowclassforwindow2; ZeroMemory(&windowclassforwindow2,sizeof(WNDCLASSEX)); windowclassforwindow2.cbClsExtra=NULL; windowclassforwindow2.cbSize=sizeof(WNDCLASSEX); windowclassforwindow2.cbWndExtra=NULL; windowclassforwindow2.hbrBackground=(HBRUSH)COLOR_WINDOW; windowclassforwindow2.hCursor=LoadCursor(NULL,IDC_ARROW); windowclassforwindow2.hIcon=NULL; windowclassforwindow2.hIconSm=NULL; windowclassforwindow2.hInstance=hInst; windowclassforwindow2.lpfnWndProc=(WNDPROC)windowprocessforwindow2; windowclassforwindow2.lpszClassName=L"window class2"; windowclassforwindow2.lpszMenuName=NULL; windowclassforwindow2.style=CS_HREDRAW|CS_VREDRAW; if(!RegisterClassEx(&windowclassforwindow2)) { int nResult=GetLastError(); MessageBox(NULL, L"Window class creation failed for window 2", L"Window Class Failed", MB_ICONERROR); } HWND handleforwindow2=CreateWindowEx(NULL, windowclassforwindow2.lpszClassName, L"Child Window", WS_OVERLAPPEDWINDOW, 200, 150, 640, 480, NULL, NULL, hInst, NULL); if(!handleforwindow2) { int nResult=GetLastError(); MessageBox(NULL, L"Window creation failed", L"Window Creation Failed", MB_ICONERROR); } ShowWindow(handleforwindow2,nShowCmd); SetParent(handleforwindow2,handleforwindow1); MSG msg; ZeroMemory(&msg,sizeof(MSG)); while (endprogram==false) { if (GetMessage(&msg,NULL,0,0)); { TranslateMessage(&msg); DispatchMessage(&msg); } if (window1closed==true && window2closed==true) { endprogram=true; } } MessageBox(NULL, L"Both Windows are closed. Program will now close.", L"", MB_ICONINFORMATION); return 0; } LRESULT CALLBACK windowprocessforwindow1(HWND handleforwindow,UINT msg,WPARAM wParam,LPARAM lParam) { switch(msg) { case WM_DESTROY: { MessageBox(NULL, L"Window 1 closed", L"Message", MB_ICONINFORMATION); window1closed=true; return 0; } break; } return DefWindowProc(handleforwindow,msg,wParam,lParam); } LRESULT CALLBACK windowprocessforwindow2(HWND handleforwindow,UINT msg,WPARAM wParam,LPARAM lParam) { switch(msg) { case WM_DESTROY: { MessageBox(NULL, L"Window 2 closed", L"Message", MB_ICONINFORMATION); window2closed=true; return 0; } break; } return DefWindowProc(handleforwindow,msg,wParam,lParam); } 

一个更复杂的例子 – 使用函数来创建窗口。

创建没有函数的每个窗口可能会使代码混乱 – 特别是如果它在if语句中。 下面的代码使用一个单独的函数来创建每个窗口。 前三个窗口有一个创建窗口按钮来创建下一个窗口。

  #include <Windows.h> LRESULT CALLBACK windowprocessforwindow1(HWND handleforwindow1,UINT message,WPARAM wParam,LPARAM lParam); LRESULT CALLBACK windowprocessforwindow2(HWND handleforwindow1,UINT message,WPARAM wParam,LPARAM lParam); LRESULT CALLBACK windowprocessforwindow3(HWND handleforwindow1,UINT message,WPARAM wParam,LPARAM lParam); LRESULT CALLBACK windowprocessforwindow4(HWND handleforwindow1,UINT message,WPARAM wParam,LPARAM lParam); #define createwindowbuttoninwindow1 101 #define createwindowbuttoninwindow2 201 #define createwindowbuttoninwindow3 301 bool window1open,window2open,window3open,window4open=false; bool windowclass1registeredbefore,windowclass2registeredbefore, windowclass3registeredbefore,windowclass4registeredbefore=false; enum windowtoopenenumt {none,window2,window3,window4}; windowtoopenenumt windowtoopenenum=none; void createwindow2(WNDCLASSEX& wc,HWND& hwnd,HINSTANCE hInst,int nShowCmd); void createwindow3(WNDCLASSEX& wc,HWND& hwnd,HINSTANCE hInst,int nShowCmd); void createwindow4(WNDCLASSEX& wc,HWND& hwnd,HINSTANCE hInst,int nShowCmd); int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR lpCmdLine,int nShowCmd) { bool endprogram=false; WNDCLASSEX windowclassforwindow2; WNDCLASSEX windowclassforwindow3; WNDCLASSEX windowclassforwindow4; HWND handleforwindow2; HWND handleforwindow3; HWND handleforwindow4; //create window 1 MSG msg; WNDCLASSEX windowclassforwindow1; ZeroMemory(&windowclassforwindow1,sizeof(WNDCLASSEX)); windowclassforwindow1.cbClsExtra=NULL; windowclassforwindow1.cbSize=sizeof(WNDCLASSEX); windowclassforwindow1.cbWndExtra=NULL; windowclassforwindow1.hbrBackground=(HBRUSH)COLOR_WINDOW; windowclassforwindow1.hCursor=LoadCursor(NULL,IDC_ARROW); windowclassforwindow1.hIcon=NULL; windowclassforwindow1.hIconSm=NULL; windowclassforwindow1.hInstance=hInst; windowclassforwindow1.lpfnWndProc=(WNDPROC)windowprocessforwindow1; windowclassforwindow1.lpszClassName=L"window class 1"; windowclassforwindow1.lpszMenuName=NULL; windowclassforwindow1.style=CS_HREDRAW|CS_VREDRAW; if(!RegisterClassEx(&windowclassforwindow1)) { int nResult=GetLastError(); MessageBox(NULL, L"Window class creation failed", L"Window Class Failed", MB_ICONERROR); } HWND handleforwindow1=CreateWindowEx(NULL, windowclassforwindow1.lpszClassName, L"Window 1", WS_OVERLAPPEDWINDOW, 200, 150, 640, 480, NULL, NULL, hInst, NULL /* No Window Creation data */ ); if(!handleforwindow1) { int nResult=GetLastError(); MessageBox(NULL, L"Window creation failed", L"Window Creation Failed", MB_ICONERROR); } ShowWindow(handleforwindow1,nShowCmd); bool endloop=false; while (endloop==false) { if (GetMessage(&msg,NULL,0,0)); { TranslateMessage(&msg); DispatchMessage(&msg); } if (windowtoopenenum !=none) { switch (windowtoopenenum) { case window2: if (window2open==false) { createwindow2(windowclassforwindow2,handleforwindow2,hInst,nShowCmd); } break; case window3: if (window3open==false) { createwindow3(windowclassforwindow3,handleforwindow3,hInst,nShowCmd); } break; case window4: if (window4open==false) { createwindow4(windowclassforwindow4,handleforwindow4,hInst,nShowCmd); } break; } windowtoopenenum=none; } if (window1open==false && window2open==false && window3open==false && window4open==false) endloop=true; } MessageBox(NULL, L"All Windows are closed. Program will now close.", L"Message", MB_ICONINFORMATION); } void createwindow2(WNDCLASSEX& wc,HWND& hwnd,HINSTANCE hInst,int nShowCmd) { if (windowclass2registeredbefore==false) { ZeroMemory(&wc,sizeof(WNDCLASSEX)); wc.cbClsExtra=NULL; wc.cbSize=sizeof(WNDCLASSEX); wc.cbWndExtra=NULL; wc.hbrBackground=(HBRUSH)COLOR_WINDOW; wc.hCursor=LoadCursor(NULL,IDC_ARROW); wc.hIcon=NULL; wc.hIconSm=NULL; wc.hInstance=hInst; wc.lpfnWndProc=(WNDPROC)windowprocessforwindow2; wc.lpszClassName=L"wc2"; wc.lpszMenuName=NULL; wc.style=CS_HREDRAW|CS_VREDRAW; if(!RegisterClassEx(&wc)) { int nResult=GetLastError(); MessageBox(NULL, L"Window class creation failed", L"Window Class Failed", MB_ICONERROR); } else windowclass2registeredbefore=true; } hwnd=CreateWindowEx(NULL, wc.lpszClassName, L"Window 2", WS_OVERLAPPEDWINDOW, 200, 170, 640, 480, NULL, NULL, hInst, NULL /* No Window Creation data */ ); if(!hwnd) { int nResult=GetLastError(); MessageBox(NULL, L"Window creation failed", L"Window Creation Failed", MB_ICONERROR); } ShowWindow(hwnd,nShowCmd); } void createwindow3(WNDCLASSEX& wc,HWND& hwnd,HINSTANCE hInst,int nShowCmd) { if (windowclass3registeredbefore==false) { ZeroMemory(&wc,sizeof(WNDCLASSEX)); wc.cbClsExtra=NULL; wc.cbSize=sizeof(WNDCLASSEX); wc.cbWndExtra=NULL; wc.hbrBackground=(HBRUSH)COLOR_WINDOW; wc.hCursor=LoadCursor(NULL,IDC_ARROW); wc.hIcon=NULL; wc.hIconSm=NULL; wc.hInstance=hInst; wc.lpfnWndProc=(WNDPROC)windowprocessforwindow3; wc.lpszClassName=L"window class 3"; wc.lpszMenuName=NULL; wc.style=CS_HREDRAW|CS_VREDRAW; if(!RegisterClassEx(&wc)) { int nResult=GetLastError(); MessageBox(NULL, L"Window class creation failed", L"Window Class Failed", MB_ICONERROR); } else windowclass3registeredbefore=true; } hwnd=CreateWindowEx(NULL, wc.lpszClassName, L"Window 3", WS_OVERLAPPEDWINDOW, 200, 190, 640, 480, NULL, NULL, hInst, NULL /* No Window Creation data */ ); if(!hwnd) { int nResult=GetLastError(); MessageBox(NULL, L"Window creation failed", L"Window Creation Failed", MB_ICONERROR); } ShowWindow(hwnd,nShowCmd); } void createwindow4(WNDCLASSEX& wc,HWND& hwnd,HINSTANCE hInst,int nShowCmd) { if (windowclass4registeredbefore==false) { ZeroMemory(&wc,sizeof(WNDCLASSEX)); wc.cbClsExtra=NULL; wc.cbSize=sizeof(WNDCLASSEX); wc.cbWndExtra=NULL; wc.hbrBackground=(HBRUSH)COLOR_WINDOW; wc.hCursor=LoadCursor(NULL,IDC_ARROW); wc.hIcon=NULL; wc.hIconSm=NULL; wc.hInstance=hInst; wc.lpfnWndProc=(WNDPROC)windowprocessforwindow4; wc.lpszClassName=L"window class 4"; wc.lpszMenuName=NULL; wc.style=CS_HREDRAW|CS_VREDRAW; if(!RegisterClassEx(&wc)) { int nResult=GetLastError(); MessageBox(NULL, L"Window class creation failed", L"Window Class Failed", MB_ICONERROR); } else windowclass4registeredbefore=true; } hwnd=CreateWindowEx(NULL, wc.lpszClassName, L"Window 4", WS_OVERLAPPEDWINDOW, 200, 210, 640, 480, NULL, NULL, hInst, NULL /* No Window Creation data */ ); if(!hwnd) { int nResult=GetLastError(); MessageBox(NULL, L"Window creation failed", L"Window Creation Failed", MB_ICONERROR); } ShowWindow(hwnd,nShowCmd); } // windows process functions LRESULT CALLBACK windowprocessforwindow1(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) { switch(message) { case WM_CREATE: window1open=true; CreateWindowEx(NULL, L"BUTTON", L"Open Window 2", WS_TABSTOP|WS_VISIBLE| WS_CHILD|BS_DEFPUSHBUTTON, 50, 220, 150, 24, hwnd, (HMENU)createwindowbuttoninwindow1, GetmoduleeHandle(NULL), NULL); break; case WM_DESTROY: window1open=false; break; case WM_COMMAND: switch LOWORD(wParam) { case createwindowbuttoninwindow1: windowtoopenenum=window2; break; } } return DefWindowProc(hwnd, message, wParam, lParam); } LRESULT CALLBACK windowprocessforwindow2(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) { switch(message) { case WM_CREATE: window2open=true; CreateWindowEx(NULL, L"BUTTON", L"Open Window 3", WS_TABSTOP|WS_VISIBLE| WS_CHILD|BS_DEFPUSHBUTTON, 50, 220, 150, 24, hwnd, (HMENU)createwindowbuttoninwindow2, GetmoduleeHandle(NULL), NULL); break; case WM_DESTROY: window2open=false; break; case WM_COMMAND: switch LOWORD(wParam) { case createwindowbuttoninwindow2: windowtoopenenum=window3; break; } } return DefWindowProc(hwnd, message, wParam, lParam); } LRESULT CALLBACK windowprocessforwindow3(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) { switch(message) { case WM_CREATE: window3open=true; CreateWindowEx(NULL, L"BUTTON", L"Open Window 4", WS_TABSTOP|WS_VISIBLE| WS_CHILD|BS_DEFPUSHBUTTON, 50, 220, 150, 24, hwnd, (HMENU)createwindowbuttoninwindow3, GetmoduleeHandle(NULL), NULL); break; case WM_DESTROY: window3open=false; break; case WM_COMMAND: switch LOWORD(wParam) { case createwindowbuttoninwindow3: windowtoopenenum=window4; break; } } return DefWindowProc(hwnd, message, wParam, lParam); } LRESULT CALLBACK windowprocessforwindow4(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) { switch(message) { case WM_DESTROY: window4open=false; break; } return DefWindowProc(hwnd, message, wParam, lParam); } 

如果关闭并重新打开一个窗口怎么办?

如果您点击关闭按钮并重新打开同一个窗口,请注意以下几点。 当关闭按钮关闭后窗口关闭时,它将被销毁。 但是销毁一个窗口不会破坏windows类。 它只能从createwindow函数中销毁窗口。 这使得上述程序中的if语句有必要只在第一次显示窗口时才创建Windows类。

一些附注

你可以使用一个Windows类创建多个窗口。 但问题是你有一个窗口处理函数来处理多个窗口。 在这个简单的例子中,这将工作得很好。 但是,窗口越是不同种类,就越需要为每个窗口创建一个单独的窗口类。

另外,多个createwindow函数可以合并成一个函数。 请注意,它们之间的唯一区别是wc.lpszClassName代码行。 但是Windows很可能彼此不同,因此将这些功能合并为一个并不是必须的 – 更重要的是不需要代码重复。

进一步阅读

具有域功能x的网站链接有关于windows设计中概念的更多细节。 链接在这里

functionx.com的主页有很好的编程学习资源。 尤其重要的是这个页面,它具有编程参考资料,如更改Windows类,创建列表框和其他窗口控件。 一般来说这也是win32编程学习的好资源。 functionx.com win32编程

functionx.com win32编程

这听起来像你想要一个多文档界面 。 这是一个例子:

http://www.codeproject.com/KB/winsdk/Sigma.aspx

您可以使用CreateWindow / CreateWindowEx创建任意数量的窗口,并根据需要(所有者/子级)使用它们之间的关系。

你可以使一个窗口“其他”拥有:

 SetWindowLongPtr(hwnd, GWLP_HWNDPARENT, (LONG_PTR) hwndParent); 

要将窗口转换为子窗口,请使用SetParent

请注意与GWLP_HWNDPARENT调用SetWindowLongPtr不行为SetParent(MSDN是错误的,我认为)。 GWLP_HWNDPARENT不会将窗口转换为“子”,而是转换为“拥有”。

我知道这已经被回答,但我只是写一个程序,通过for循环打开任意数量的窗口。

这是我的版本。 基本上,它重用相同的类生成器来建立多个窗口。 你可以创建尽可能多的,你想要的。 只要确保相应地调整HWND []和WNDCLASSEX wc []数组。

注1:这段代码使用从WinMain函数派生的全局ApplicationInstance。 在您的WinMain中,将收到的hInstance分配给ApplicationInstance,在这个例子中假定全局可用。 这是您的主要应用程序窗口实例。

注2:当然,你必须已经预先写好了WinProc例程,并且包含在另一个头文件的某个地方,或者刚好在上面(在这个例子中没有显示)。在这个代码中,它被引用为WinProc,当它被传递到PopulateClass(WNDPROC进程)

注3:SpawnWindow支持“居中”和“最大化”标志。 他们做什么是不言自明的。

此外,窗口类的名称是自动生成的,所以你不必担心命名它,只是分配一个很好的基名。

 int WindowCounter = 0; WNDCLASSEX wc[1000]; HWND hwnd[1000]; char class_name[256]; // for auto class name generation void PopulateClass(WNDPROC process) { ZeroMemory(&wc[WindowCounter], sizeof(WNDCLASSEX)); wc[WindowCounter].cbSize = sizeof(WNDCLASSEX); wc[WindowCounter].style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC; wc[WindowCounter].lpfnWndProc = process; wc[WindowCounter].cbClsExtra = 0; wc[WindowCounter].cbWndExtra = 0; wc[WindowCounter].hInstance = ApplicationInstance; wc[WindowCounter].hIcon = LoadIcon(nullptr, IDI_APPLICATION); wc[WindowCounter].hCursor = LoadCursor(nullptr, IDC_ARROW); wc[WindowCounter].hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); wc[WindowCounter].lpszMenuName = nullptr; sprintf(class_name, "WindowClass%d", WindowCounter); wc[WindowCounter].lpszClassName = class_name; wc[WindowCounter].hIconSm = nullptr; } 

现在,让我们通过提供一个SpawnWindow函数把它放在一起!

 HWND SpawnWindow(int x, int y, int width, int height, bool centered = false, bool maximized = false) { PopulateClass(WinProc); RegisterClassEx(&wc[ WindowCounter ]); int config_style = WS_OVERLAPPEDWINDOW; if (maximized) { width = GetSystemMetrics(SM_CXFULLSCREEN); height = GetSystemMetrics(SM_CYFULLSCREEN); config_style = WS_OVERLAPPEDWINDOW | WS_MAXIMIZE; } if (centered) { x = (GetSystemMetrics(SM_CXFULLSCREEN) / 2) - (width / 2); y = (GetSystemMetrics(SM_CYFULLSCREEN) / 2) - (height / 2); } hwnd[WindowCounter] = CreateWindowEx(NULL, wc[WindowCounter].lpszClassName, config.namever(), WS_OVERLAPPEDWINDOW, x, y, width, height, nullptr, nullptr, ApplicationInstance, nullptr); HWND returnID = hwnd[WindowCounter]; ShowWindow(hwnd[WindowCounter++], SW_SHOW); return returnID; } 

最后,只需使用一行代码即可创建尽可能多的窗口:

 void CreateWindows() { HWND PrimaryWindow1 = SpawnWindow(500, 500, 250, 250); HWND PrimaryWindow2 = SpawnWindow(500, 500, 250, 250, true); HWND PrimaryWindow3 = SpawnWindow(500, 500, 250, 250, true, true); HWND PrimaryWindow4 = SpawnWindow(100, 100, 150, 150); HWND PrimaryWindow5 = SpawnWindow(450, 500, 350, 150); } 

在进入主循环之前,从WinMain中调用CreateWindows()。

希望这可以帮助那里的人。