Чтобы создать более одного окна, повторите все шаги, которые вы сделали, когда создали первое окно, чтобы создать второе окно. Хороший способ сделать это - скопировать и вставить весь код из первого окна. Затем выполните поиск и замените, в котором вы заменяете все имена первого окна уникальными именами для второго окна. Код, в котором я это делаю, приведен ниже.
Самое важное, на что следует обратить внимание, - это то, что класс windows для второго окна должен иметь уникальное имя в коде
line "windowclassforwindow2.lpszClassName =" window class2 ". Если у него нет уникального имени, регистрация окон завершится неудачей.
#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 только в том случае, если окно отображается впервые.
Некоторые примечания
Вы можете создать несколько окон, используя только один класс окон. Но проблема в том, что у вас есть одна оконная функция для работы с несколькими окнами. Это будет хорошо работать в этом простом примере. Но чем более разнородны окна, тем больше будет необходимости создавать отдельный класс окон для каждого окна.
Также несколько функций createwindow можно было бы объединить в одну функцию. Обратите внимание, что единственной разницей между ними была строка кода wc.lpszClassName. Но Windows, вероятно, будет отличаться друг от друга, поэтому объединять функции в одну не нужно - это скорее предпочтение просто не иметь кода, повторяющего вещи.
Дополнительная литература
Ссылка на веб-сайт с функцией домена x содержит более подробную информацию о концепциях дизайна окон. Ссылка здесь
Домашняя страница на functionx.com имеет хорошие учебные ресурсы по программированию.
Особенно важна эта страница, на которой есть справочные материалы по программированию для таких вещей, как изменение класса окон, создание списков и других элементов управления окнами. Это также хороший ресурс для обучения программированию на win32 в целом.
functionx.com win32 программирование
functionx.com win32 программирование