Para crear más de una ventana, repita todos los pasos que hizo cuando creó la primera ventana para crear una segunda ventana. Una buena forma de hacerlo es copiar y pegar todo el código de la primera ventana. Luego busque y reemplace en el que reemplace todos los nombres de la primera ventana con nombres únicos para la segunda ventana. El código en el que hago eso está abajo.
Lo más importante a tener en cuenta es que la clase de Windows para la segunda ventana debe tener un nombre único en el código línea "windowclassforwindow2.lpszClassName =" window class2 ". Si no tiene un nombre único, el el registro de windows fallará.
#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);
}
un ejemplo que utilizan funciones para crear ventanas.
la creación de cada ventana sin una función se puede hacer el código desordenado, sobre todo si se trata de si las declaraciones más complejo. El código a continuación usa un f por separado unction para crear cada ventana. Las primeras tres ventanas tienen un botón de crear ventana para crear la siguiente ventana.
#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);
}
Lo que si cierra y vuelve a abrir una ventana?
Si hace clic en el botón de cerrar y vuelve a abrir la misma ventana, tenga en cuenta lo siguiente. Cuando la ventana se cierra después de cerrar el botón de cierre, se destruirá. Pero destruir una ventana no destruye la clase de Windows. Solo destruye la ventana de la función createwindow. Esto hace que sea necesario para la instrucción if en el programa anterior que solo crea la clase de Windows si es la primera vez que se muestra la ventana.
Algunos lado señala
Se puede crear múltiples ventanas con una sola clase de ventanas. Pero el problema con eso es que tiene una función de proceso de Windows para tratar con más de una ventana. Eso funcionaría bien en este simple ejemplo. Pero cuanto más heterogéneas sean las ventanas, mayor será la necesidad de crear una clase de Windows separada para cada ventana.
También las múltiples funciones de createwindow se podrían haber combinado en una función. Tenga en cuenta que la única diferencia entre ellos era la línea de código wc.lpszClassName. Pero es probable que Windows sea diferente el uno del otro, por lo que no es necesario combinar las funciones en una: es más una preferencia que simplemente no tener código repitiendo cosas.
Lectura adicional
El enlace en la página web con el dominio functionx tiene más detalles sobre los conceptos en el diseño de las ventanas. El enlace es here
La página de inicio en functionx.com tiene buenos recursos de aprendizaje de programación. Especialmente importante es esta página que tiene material de referencia de programación para cosas tales como cambiar la clase de Windows, crear listboxes y otros controles de Windows. También es un buen recurso para el aprendizaje de programación win32 en general. functionx.com programación Win32
functionx.com win32 programming
Lo tengo trabajando, finalmente. Funcionó cuando modifiqué mi rutina que crea ventanas permitiéndole registrar una clase de ventana usando una cadena ClassName diferente. ¿Por qué tendría que hacer una clase de ventana separada para la segunda ventana si la funcionalidad no es la misma? –
@Steven Lu: no estoy seguro. La prueba que ejecuté para verificar dos veces solo registró una clase de ventana y pude abrir CreateWindow dos veces. Por supuesto, esto significa que comparten un WndProc. No tienes datos estáticos dentro del WndProc, ¿o sí? – JustJeff
Todavía estaba usando el mismo proc de ventana, pero tenía que ser una clase de ventana diferente, es decir, tenía que llamar a 'RegisterClassEx' con un' WNDCLASSEX :: lpszClassName' diferente. ¿Esto es normal? –