16 Stimmen

Mehrere Fenster mit Win32 API erstellen

Ich sehe viele Tutorials und Artikel, die mir zeigen, wie man ein einfaches Windows-Programm erstellt, was großartig ist, aber keiner von ihnen zeigt mir, wie man mehrere Windows-Programme erstellt.

Im Moment habe ich einen funktionierenden Code, der ein mehrschichtiges Fenster erstellt und zeichnet, und ich kann Sachen mit GDI überblenden, um alles zu zeichnen, was ich will, es herumzuziehen, es sogar transparent zu machen, usw.

Aber ich wollte einen zweiten rechteckigen Bereich, auf den ich zeichnen, um ihn herumziehen kann, usw. Mit anderen Worten, ein zweites Fenster. Wahrscheinlich soll es ein untergeordnetes Fenster sein. Die Frage ist, wie kann ich es machen?

Wenn jemand gute Ressourcen (vorzugsweise online) wie Artikel oder Tutorien für die Fensterverwaltung in der Windows-API kennt, teilen Sie diese bitte mit.

16voto

rauprog Punkte 233

Um mehr als ein Fenster zu erstellen, wiederholen Sie alle Schritte, die Sie beim Erstellen des ersten Fensters durchgeführt haben, um ein zweites Fenster zu erstellen. Eine gute Möglichkeit ist, den gesamten Code des ersten Fensters zu kopieren und einzufügen. Führen Sie dann eine Such- und Ersetzungsoperation durch, bei der Sie alle Namen des ersten Fensters durch eindeutige Namen für das zweite Fenster ersetzen. Der Code, in dem ich genau das tue, steht unten.

Das Wichtigste ist, dass die Windows-Klasse für das zweite Fenster einen eindeutigen Namen im Code haben sollte Zeile "windowclassforwindow2.lpszClassName="window class2" haben sollte. Wenn sie keinen eindeutigen Namen hat, schlägt die Windows-Registrierung fehl.

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

Ein komplexeres Beispiel - die Verwendung von Funktionen zur Erstellung von Windows.

Die Erstellung jedes Fensters ohne eine Funktion kann den Code unübersichtlich machen - vor allem, wenn sie in if-Anweisungen enthalten ist. Der folgende Code verwendet eine separate Funktion, um jedes Fenster zu erstellen. Die ersten drei Fenster haben eine Schaltfläche "Fenster erstellen", um das nächste Fenster zu erstellen.

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

Was passiert, wenn Sie ein Fenster schließen und wieder öffnen?

Wenn Sie auf die Schaltfläche "Schließen" klicken und dasselbe Fenster erneut öffnen, sehen Sie Folgendes. Wenn das Fenster geschlossen wird, nachdem die Schaltfläche "Schließen" geschlossen wurde, wird es zerstört. Aber das Zerstören eines Fensters zerstört nicht die Klasse Windows. Es wird nur das Fenster aus der Funktion createwindow zerstört. Dies macht die if-Anweisung im obigen Programm erforderlich, die die Windows-Klasse nur dann anlegt, wenn das Fenster zum ersten Mal angezeigt wird.

Einige Randnotizen

Sie können mehrere Fenster mit nur einer Windows-Klasse erstellen. Das Problem dabei ist jedoch, dass Sie eine Windows-Prozessfunktion haben, die mit mehr als einem Fenster arbeitet. Das würde in diesem einfachen Beispiel gut funktionieren. Aber je heterogener die Fenster sind, desto notwendiger wäre es, für jedes Fenster eine eigene Windows-Klasse zu erstellen.

Auch die mehrfachen "createwindow"-Funktionen hätten in einer Funktion zusammengefasst werden können. Beachten Sie, dass der einzige Unterschied zwischen ihnen die Codezeile wc.lpszClassName war. Aber Windows unterscheiden sich wahrscheinlich voneinander, so dass es nicht notwendig ist, die Funktionen zu einer einzigen zusammenzufassen - es ist eher eine Vorliebe dafür, dass sich der Code nicht wiederholt.

Weitere Lektüre

Der Link auf der Website mit der Domain functionx enthält weitere Einzelheiten zu den Konzepten im Windows-Design. Der Link lautet ici

Die Homepage von functionx.com bietet gute Ressourcen zum Programmieren lernen. Besonders wichtig ist diese Seite, die Programmierreferenzmaterial für Dinge wie das Ändern der Windows-Klasse, das Erstellen von Listboxen und anderen Windows-Steuerungen enthält. Sie ist auch eine gute Ressource für das Erlernen der Win32-Programmierung im Allgemeinen. functionx.com win32-Programmierung

functionx.com win32 Programmierung

13voto

JustJeff Punkte 12130

Sie können CreateWindow() mehr als einmal drücken, wenn Sie wollen. Die Nachrichtenschleife in Ihrem WinMain wird Ereignisse an alle von WinMain erstellten Fenster weitergeben. Sie können sogar zwei überlappende Fenster erstellen und das übergeordnete Fenster des zweiten Fensters auf das Handle des ersten Fensters setzen, wenn Sie wollen.

3voto

Robert Harvey Punkte 173098

Es klingt, als wollten Sie eine Schnittstelle für mehrere Dokumente . Hier ist ein Beispiel dafür:

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

3voto

InfiniteStack Punkte 414

Ich weiß, dass dies bereits beantwortet wurde, aber ich habe gerade ein Programm geschrieben, das eine beliebige Anzahl von Fenstern über eine for-Schleife öffnet.

Hier ist meine Version. Im Grunde verwendet sie denselben Klassengenerator, um mehrere Windows zu erstellen. Sie können so viele erstellen, wie Sie wollen. Stellen Sie nur sicher, dass Sie Ihre HWND[]- und WNDCLASSEX wc[]-Arrays entsprechend anpassen.

Hinweis 1: Dieser Code verwendet eine globale ApplicationInstance, die von der WinMain-Funktion abgeleitet ist. Weisen Sie in Ihrem WinMain die empfangene hInstance der ApplicationInstance zu, die in diesem Beispiel als global verfügbar angenommen wird. Dies ist Ihre primäre Anwendungsfensterinstanz.

Hinweis 2: Natürlich müssen Sie die WinProc-Routine bereits geschrieben haben und irgendwo in einer anderen Header-Datei oder direkt darüber einbinden (in diesem Beispiel nicht gezeigt). In diesem Code wird sie als WinProc referenziert, wenn sie an PopulateClass(WNDPROC process) übergeben wird

Hinweis 3: SpawnWindow unterstützt die Flags "zentriert" und "maximiert". Was sie bewirken, ist selbsterklärend.

Außerdem wird der Name der Fensterklasse automatisch generiert, so dass Sie sich keine Gedanken über die Namensgebung machen müssen, sondern ihr einfach einen guten Basisnamen zuweisen können.

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

Fügen wir nun alles zusammen, indem wir eine SpawnWindow-Funktion bereitstellen!

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

Schließlich können Sie beliebig viele Fenster mit jeweils nur einer einzigen Codezeile erstellen:

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

Rufen Sie CreateWindows() aus Ihrer WinMain auf, bevor Sie in die Hauptschleife eintreten.

Ich hoffe, das hilft jemandem da draußen.

Verwendung eines einzigen WinProc für alle Windows

Beachten Sie, dass dies eine zusätzliche Änderung des obigen Codes erfordert. Insbesondere die Übergabe eines benutzerdefinierten Klassennamens an die Funktion SpawnWindow, der jedes Fenster repräsentiert. Zum Beispiel: "WindowClass_App", wobei "WindowClass_" ein statischer Teil des Namens sein kann, und der tatsächliche Bezeichner wäre einfach: "App", "Toolbox", "Sidebar", "AnotherCustomWindow", usw. Definieren Sie sie zunächst:

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

Ich habe eine Funktion geschrieben, die einen String in eine int ID umwandelt. Diese ID wird verwendet, um innerhalb der einzelnen WinProc-Funktion zu verzweigen, je nachdem, welche Fensterklasse die Nachricht erhalten hat:

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

Und schließlich das WinProc selbst:

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

       ...

Dies ist das Grundmuster. Natürlich können Sie es auf jede beliebige Art und Weise basteln, so habe ich es gemacht, es ist einfach und funktioniert für mich.

2voto

Hernán Punkte 4349

Mit CreateWindow/CreateWindowEx können Sie beliebig viele Fenster erstellen, wobei die Beziehung zwischen den Fenstern beliebig sein kann (Eigentümer/Kind).

Sie können ein Fenster zum "Eigentum" eines anderen machen:

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

Um ein Fenster in ein untergeordnetes Fenster zu konvertieren, verwenden Sie SetParent .

Beachten Sie, dass die SetWindowLongPtr Aufruf mit GWLP_HWNDPARENT verhält sich nicht wie SetParent (MSDN ist falsch auf diese ich denke). GWLP_HWNDPARENT konvertiert ein Fenster nicht in "Kind", sondern in "Eigentum".

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X