// Two Windows.cpp : Defines the entry point for the application.
// DEMO2_5.CPP - Creates two windows based on the same
// window class
// INCLUDES ///////////////////////////////////////////////
#define WIN32_LEAN_AND_MEAN // just say no to MFC
#include <windows.h> // include all the windows headers
#include <windowsx.h> // include useful macros
#include <stdio.h>
#include <math.h>
#include <stdafx.h>
// DEFINES ////////////////////////////////////////////////
// defines for windows
#define WINDOW_CLASS_NAME "WINCLASS1"
#define WINDOW_CLASS_NAME2 "WINCLASS2"
// GLOBALS ////////////////////////////////////////////////
HWND hWindow1 = NULL;
HWND hWindow2 = NULL;
// FUNCTIONS //////////////////////////////////////////////
LRESULT CALLBACK WindowProc(HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam)
{
// this is the main message handler of the system
PAINTSTRUCT ps; // used in WM_PAINT
HDC hdc; // handle to a device context
// what is the message
switch(msg)
{
case WM_CREATE:
{
// do initialization stuff here
// return success
return(0);
} break;
case WM_PAINT:
{
// simply validate the window
hdc = BeginPaint(hwnd,&ps);
// you would do all your painting here
EndPaint(hwnd,&ps);
// return success
return(0);
} break;
case WM_DESTROY:
{
// kill the application, this sends a WM_QUIT message
if( hwnd == hWindow1 )
hWindow1 = NULL;
if( hwnd == hWindow2 )
hWindow2 = NULL;
if((!hWindow1) && (!hWindow2) )
PostQuitMessage(0);
// return success
return(0);
} break;
default:break;
} // end switch
// process any messages that we didn't take care of
return (DefWindowProc(hwnd, msg, wparam, lparam));
} // end WinProc
// WINMAIN ////////////////////////////////////////////////
int WINAPI WinMain( HINSTANCE hinstance,
HINSTANCE hprevinstance,
LPSTR lpcmdline,
int ncmdshow)
{
WNDCLASSEX winclass; // this will hold the class we create
WNDCLASSEX winclass2;
MSG msg; // generic message
// first fill in the window class stucture
winclass.cbSize = sizeof(WNDCLASSEX);
winclass.style = CS_DBLCLKS | CS_OWNDC |
CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc = WindowProc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hinstance;
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass.lpszMenuName = NULL;
winclass.lpszClassName = WINDOW_CLASS_NAME;
winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
// winclass2 struct
winclass2.cbSize = sizeof(WNDCLASSEX);
winclass2.style = CS_DBLCLKS | CS_OWNDC |
CS_HREDRAW | CS_VREDRAW;
winclass2.lpfnWndProc = WindowProc;
winclass2.cbClsExtra = 0;
winclass2.cbWndExtra = 0;
winclass2.hInstance = hinstance;
winclass2.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winclass2.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass2.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass2.lpszMenuName = NULL;
winclass2.lpszClassName = WINDOW_CLASS_NAME2;
winclass2.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
// register the window class
if (!RegisterClassEx(&winclass))
return(0);
// register the window2 class
if (!RegisterClassEx(&winclass2))
return(0);
// create the first window
if (!(hWindow1 = CreateWindowEx(NULL, // extended style
WINDOW_CLASS_NAME, // class
"Window 1 Based on WINCLASS1", // title
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0,0, // initial x,y
400,400, // initial width, height
NULL, // handle to parent
NULL, // handle to menu
hinstance,// instance of this application
NULL))) // extra creation parms
return(0);
// create the second window
if (!(hWindow2 = CreateWindowEx(NULL, // extended style
WINDOW_CLASS_NAME2, // class
"Window 2 Based on WINCLASS2", // title
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
100,100, // initial x,y
400,400, // initial width, height
NULL, // handle to parent
NULL, // handle to menu
hinstance,// instance of this application
NULL))) // extra creation parms
return(0);
// enter main event loop, but this time we use PeekMessage()
// instead of GetMessage() to retrieve messages
while(TRUE)
{
// test if there is a message in queue, if so get it
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
// test if this is a quit
if (msg.message == WM_QUIT)
break;
// translate any accelerator keys
TranslateMessage(&msg);
// send the message to the window proc
DispatchMessage(&msg);
} // end if
// main game processing goes here
} // end while
// return to Windows like this
return(msg.wParam);
} // end WinMain
///////////////////////////////////////////////////////////
It executes perfectly, but I'm not sure how WindowProc works. How does it know which window need to be repainted? I'm my code, it doesn't appear to know the handle of either window.
Somebody please help so I can move on to the next chapter.
Edited by - Brian Jones on December 12, 2001 5:24:02 PM
Edited by - Brian Jones on December 12, 2001 5:28:01 PM
TOTWGPG
Hello, I am at the latter part of the second chapter in this book. I've made a program that opens two different windows, based on two different classes.
I don't have a signature
If you look at the function declaration, you will see hwnd.
LRESULT CALLBACK WindowProc(HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam) {
....
}
When you window gets a system message such as window close, resize, repaint, etc....it calls WindowProc with hwnd, which is a handle to the current window (ie, itself). So when WindowProc is called, it does it''s work on hwnd, which points to the window that called it. Make sense?
And if you notice throughout your code below, you call all the functions to manipulate the window with hwnd again. So you always do the work on the calling window.
Good to see you asking the questions, g''luck with it all =)
R.
LRESULT CALLBACK WindowProc(HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam) {
....
}
When you window gets a system message such as window close, resize, repaint, etc....it calls WindowProc with hwnd, which is a handle to the current window (ie, itself). So when WindowProc is called, it does it''s work on hwnd, which points to the window that called it. Make sense?
And if you notice throughout your code below, you call all the functions to manipulate the window with hwnd again. So you always do the work on the calling window.
Good to see you asking the questions, g''luck with it all =)
R.
But, hWindow1, and hWindow2 are the handles to the two windows. How would I pass both of those handles to WindowProc?
I don't have a signature
Well, those handles are just pointers. You have more than one pointer to each window.
Say for example you tell your window to minimize. The window you created knows that it''s callback function is WindowProc because you created a Window Class and told it what function to use. So, when you minimize that window, it will call WindowProc for you using using hWindow1 or hWindow2 depending on which window does the calling. If you minimize hWindow2, it''ll call Windowproc with hWindow2 as it''s first paramater. Windowproc just create a new pointer called hwnd to point to hWindow2. At this point, hwnd = hWindow2.
Same thing if it was hWindow1 that sent a message to WindowProc. If it didn''t work this way, you''d have to write a seperate WindowProc for each Window. If you had an application with 10 windows, that''d be 10 WindowProcs?! Waste of time. Instead, you can create a common WindowProc and maybe a special WindowProc when you want the window to act differently or just write a lot of code to compare hwnd to hWindow1, hWindow2, etc. Just like you did in the code from the book. If you look at WM_DESTROY in WindowProc, you can see code where you see if hwnd == hWindow1 or if hwnd == hWindow2.
R.
Say for example you tell your window to minimize. The window you created knows that it''s callback function is WindowProc because you created a Window Class and told it what function to use. So, when you minimize that window, it will call WindowProc for you using using hWindow1 or hWindow2 depending on which window does the calling. If you minimize hWindow2, it''ll call Windowproc with hWindow2 as it''s first paramater. Windowproc just create a new pointer called hwnd to point to hWindow2. At this point, hwnd = hWindow2.
Same thing if it was hWindow1 that sent a message to WindowProc. If it didn''t work this way, you''d have to write a seperate WindowProc for each Window. If you had an application with 10 windows, that''d be 10 WindowProcs?! Waste of time. Instead, you can create a common WindowProc and maybe a special WindowProc when you want the window to act differently or just write a lot of code to compare hwnd to hWindow1, hWindow2, etc. Just like you did in the code from the book. If you look at WM_DESTROY in WindowProc, you can see code where you see if hwnd == hWindow1 or if hwnd == hWindow2.
R.
Easily, they are both based on the same WndProc. In your WNDCLASS struct you assign the same WndProc to both.
This they both point to the same function, in this case the WndProc.
ECKILLER
This they both point to the same function, in this case the WndProc.
ECKILLER
ECKILLER
Ahhh I get it. I forgot about that. This Windows programming is hard. One more thing though
Somebody please explain that. That code is not mine, somebody added it to the program when I was writing it.
case WM_DESTROY:{ // kill the application, this sends WM_QUIT if( hwnd == hWindow1 ) hWindow1 = NULL; if( hwnd == hWindow2 ) hWindow2 = NULL; if((!hWindow1) && (!hWindow2) )PostQuitMessage(0); // return success return(0);} break;
Somebody please explain that. That code is not mine, somebody added it to the program when I was writing it.
I don't have a signature
quote: if( hwnd == hWindow1 )
hWindow1 = NULL;
if( hwnd == hWindow2 )
hWindow2 = NULL;
Assign whichever window received the WM_DESTROY message to point to NULL. Whoever wrote it felt that it was necessary so that the application would be able to quit if both Windows had been closed. It was also necessary to explicitly refer to the variables by name because the window procedure gets a copy of the handle, not the original.
Not exactly a stroke of elegant genious, but it works.
[ GDNet Start Here | GDNet FAQ | MS RTFM | STL | Google ]
Thanks to Kylotan for the idea!
Ok.... I get it. But what does the last part mean?
Everybody must be like "God this guy can''t figure out anything
for himself."
if((!hWindow1) && (!hWindow2) )
Everybody must be like "God this guy can''t figure out anything
for himself."
I don't have a signature
Read it out: "if not hWindow1 and not hWindow2..."
In other words, if both of them are "not" (zero values, such as NULL).
[ GDNet Start Here | GDNet FAQ | MS RTFM | STL | Google ]
Thanks to Kylotan for the idea!
In other words, if both of them are "not" (zero values, such as NULL).
[ GDNet Start Here | GDNet FAQ | MS RTFM | STL | Google ]
Thanks to Kylotan for the idea!
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement