代码之家  ›  专栏  ›  技术社区  ›  Steven Lu

如何使用win32 api创建多个窗口

  •  9
  • Steven Lu  · 技术社区  · 14 年前

    我看到很多教程和文章向我展示了如何制作一个简单的Windows程序,这很好,但没有一篇文章向我展示了如何制作多个窗口。

    现在,我有了可以创建和绘制分层窗口的工作代码,我可以使用gdi在窗口上绘制任何我想要的东西,拖动它,甚至使它透明,等等。

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

    另外,如果有人知道任何好的资源(最好是在线的),比如WindowsAPI中的关于窗口管理的文章或教程,请分享。

    5 回复  |  直到 6 年前
        1
  •  8
  •   JustJeff    14 年前

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

        2
  •  9
  •   rauprog    9 年前

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

    最重要的是要注意的是,第二个窗口的Windows类在代码处应该有一个唯一的名称。 line“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,
                    GetModuleHandle(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,
                    GetModuleHandle(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,
                    GetModuleHandle(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类创建多个窗口。但问题在于,您有一个Windows进程函数来处理多个窗口。在这个简单的例子中,这很好。但是,窗口越是异构,就越需要为每个窗口创建一个单独的Windows类。

    另外,多个CreateWindow函数也可以组合成一个函数。注意,它们之间唯一的区别是wc.lpszClassName代码行。但是,窗口可能彼此不同,因此将函数组合成一个函数是不必要的,它更倾向于不让代码重复。

    进一步阅读

    网站上具有域功能的链接提供了有关Windows设计概念的更多详细信息。链接是 here

    functionx.com的主页具有良好的编程学习资源。 特别重要的是,该页面具有编程参考资料,用于更改Windows类、创建列表框和其他Windows控件。对于一般的win32编程学习来说,它也是一个很好的资源。 函数x.com win32编程

    functionx.com win32 programming

        3
  •  3
  •   Robert Harvey    14 年前
        4
  •  2
  •   Hernán    14 年前

    您可以使用CreateWindow/CreateWindowEx创建任意多个窗口,并根据需要在它们之间建立关系(所有者/子对象)。

    您可以通过以下方式使窗口“归他人所有”:

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

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

    请注意 SetWindowLongPtr 打电话 GWLP_HWNDPARENT 不表现为setparent(我认为msdn在这方面是错误的)。 GWLPHWNDN亲本 不将窗口转换为“子”,而是转换为“拥有”。

        5
  •  2
  •   InfiniteStack    6 年前

    我知道这个问题已经得到了解决,但我只是在编写一个程序,通过for循环打开任意数量的窗口。

    这是我的版本。基本上,它重用同一类生成器来构建多个窗口。您可以创建任意多个。只需确保相应地调整您的hwnd[]和wndclassex wc[]数组。

    注1:这段代码使用一个全局应用程序实例,它是从winmain函数派生的。在winmain中,将接收到的hinstance分配给applicationInstance,在本例中,假定该实例全局可用。这是您的主应用程序窗口实例。

    注2:当然,您必须预先编写winproc例程,并将其包含在另一个头文件中的某个位置,或者就在上面(本例中未显示)。在此代码中,当它传递到populateclass(wndproc进程)时,它被引用为winproc。

    注3:生成窗口支持“居中”和“最大化”标志。他们所做的是不言自明的。

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

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

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

    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()。

    希望这能帮助别人。

    对所有窗口使用单个winproc

    注意,这将需要对上述代码进行额外的修改。特别是,将一个自定义类名传递给SpawWindow函数,表示每个窗口。例如:“windowclass_-app”,其中“windowclass_uu”可以是名称的静态部分,而实际的标识符将只是:“app”、“toolbox”、“sidebar”、“anothercustomwindow”等。首先定义它们:

    #define WindowClass_App                    0
    #define WindowClass_Layers                 2
    #define WindowClass_OpenGL                 3
    /* ...etc... */
    

    我编写了一个将字符串转换为int id的函数。该id将用于在单个winproc函数中进行分支,根据接收消息的窗口类:

    int IdentifyWindowClassID(const char *lpClassName) {
        int WindowClassID = -1;
        // Convert string names to integers, because C++ switch does not support strings
        if (strcmp(lpClassName, "WindowClass_App") == 0) WindowClassID = WindowClass_App;
        if (strcmp(lpClassName, "WindowClass_Layers") == 0) WindowClassID = WindowClass_Layers;
        if (strcmp(lpClassName, "WindowClass_OpenGL") == 0) WindowClassID = WindowClass_OpenGL;
        /* etc */
        return WindowClassID;
    }
    

    最后,winproc本身:

    long __stdcall WinProc(HWND hwnd, unsigned int msg, WPARAM wparam, LPARAM lparam)
    {
        char lpClassName[128];
        GetClassName(hwnd, lpClassName, 128);
    
        int WindowClassID = IdentifyWindowClassID( lpClassName );
    
        switch (WindowClassID)
        {
            /* 1.) Main application window */
            case WindowClass_App: { 
                switch (msg) {    
                    case WM_CREATE: {
                        /* ...code... */
                    }
                /* ...code... */
            }
    
            /* 2.) Layers window */
            case WindowClass_Layers: {
                switch (msg) {    
                    case WM_CREATE: {
                        /* ...code... */
                    }
                /* ...code... */
            }
    
            /* 3.) OpenGL view window... */
    
           ...
    

    这是基本模式。当然,你可以用任何你想要的方式来制作它,这就是我做它的方式,它很简单,而且对我很有用。