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