case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
It’s easy to get worried when you think about the fact that this is one of the
simplest Windows programs you can write, and it’s still over 200 lines
long. The good thing is that the code above is more or less common to all
Windows programs. Most Windows programmers don’t remember the
exact order everything goes in; they just copy the working Windows initial
-
ization code from a previous application and use it like it is their own.
Explaining the Code
Every C/C++ program has its entry point in main(), where it is passed
control from the operating system. In Windows, things work a little differ
-
ently. There is some code that the Win32 API runs first, before letting your
code run. The actual stub for main() lies deep within the Win32 DLLs.
However, this application starts at a different point: with a function called
WinMain(). Windows does its setup work when your application is first
run, and then calls WinMain(). This is why when you debug a Windows
app “WinMain” doesn’t appear at the bottom of the call stack; the internal
DLL functions that called it are. WinMain() is passed the following
parameters (in order):
n
The instance of the application (another handle, this one representing
an instantiation of a running executable). Each process has a separate
instance handle that uniquely identifies the process to Windows. This is
Chapter 1: Windows n 11
different from a window handle, as each application can have many
windows under its control. You need to hold on to this instance, as cer
-
tain Windows API calls need to know what instance is calling them.
Think of an instance as just a copy, or even as an image, of the execut
-
able in memory. Each executable has a handle so that Windows can tell
them apart, manage them, and so on.
n
An HINSTANCE of another copy of your application currently running.
Back in the days before machines had much memory, Windows would
have multiple instances of a running program share memory. These
days each process is run in its own separate memory space, so this
parameter is always NULL. It remains this way so that legacy Windows
applications still work.
n
A pointer to the command line string. When the user drags a file onto
an executable in Explorer (not a running copy of the program), Win
-
dows runs the program with the first parameter of the command line
being the path and filename of the file dragged onto it.
n
A set of flags describing how the window should initially be drawn
(such as full-screen, minimized, etc.).
The conceptual flow of the function is to do the following:
WinMain
Register the application class with Windows
Create the main window
while( not been told to exit )
Process any messages that Windows has sent
MyRegisterClass() takes the application instance and tells Windows about
the application (registering it, in essence). InitInstance() creates the pri
-
mary window on the screen and starts it drawing. Then the code enters a
while loop that remains in execution until the application quits. The func
-
tion GetMessage() looks at the message queue. It always returns 1 unless
there is a specific system message in the queue: This is the “Quit now”
message and has the message ID WM_QUIT. If there is a message in the
queue, GetMessage() will remove it and fill it into the message structure,
which is the “msg” variable above. Inside the while loop, you first take the
message and translate it using a function called TranslateMessage().
This is a convenience function. When you receive a message saying a
key has been pressed or released, you get the specific key as a virtual key
code. The actual values for the IDs are arbitrary, but the namespace is what
you care about: When the letter “a” is pressed, one of the message parame
-
ters is equivalent to the #define VK_A. Since that nomenclature is a pain
to deal with if you’re doing something like text input, TranslateMessage()
does some housekeeping and converts the parameter from VK_A to
(char)‘a’. This makes processing regular text input much easier. Keys with
-
out clear ASCII equivalents, such as Page Up and Left Arrow, keep their
12 n Chapter 1: Windows

Get Advanced 3D Game Programming with DirectX 10.0 now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.