如何使用Win32 API创建多个窗口

时间:2010-05-22 01:46:59

标签: c++ windows winapi

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

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

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

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

5 个答案:

答案 0 :(得分: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进程函数来处理多个窗口。在这个简单的例子中,这可行。但是窗口越异构,就越需要为每个窗口创建一个单独的窗口类。

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

进一步阅读

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

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

functionx.com win32 programming

答案 1 :(得分:8)

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

答案 2 :(得分:3)

答案 3 :(得分:2)

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

你可以通过以下方式让一个窗口“拥有”:

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

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

请注意,使用SetWindowLongPtr的{​​{1}}调用不会像SetParent一样(我认为MSDN错误)。 GWLP_HWNDPARENT不会将窗口转换为“子”,而是转换为“拥有”。

答案 4 :(得分:2)

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

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

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

注意2:当然,您必须预先编写WinProc例程,并将其包含在另一个头文件中,或者仅在上面(本示例中未显示)。在此代码中,它被引用为WinProc,何时将其传递给PopulateClass(WNDPROC流程)

注3:SpawnWindow支持&#34;居中&#34;并且&#34;最大化&#34;标志。他们所做的是不言自明的。

此外,窗口类名称是自动生成的,因此您无需担心命名它,只需为其指定一个良好的基本名称。

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

希望这可以帮助那些人。

为所有窗口使用单个WinProc

注意,这将需要对上述代码进行额外修改。特别是,将自定义类名传递给SpawnWindow函数,表示每个窗口。例如:&#34; WindowClass_App&#34;,其中&#34; WindowClass _&#34;可以是名称的静态部分,实际的标识符只是:&#34; App&#34;,&#34;工具箱&#34;,&#34;边栏&#34;,&#34; AnotherCustomWindow&#34 ;等等。首先定义它们:

#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... */

       ...

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