1.1 Windows programming basics

If you are a DOS programmer, you will find Windows programming is very different. Before I do more comparsion, let us have a look of a simple Win32 program.

Sample1.cpp

#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

HINSTANCE	g_hInstance = NULL;
HWND		g_hWndMain = NULL;

LRESULT CALLBACK WindowProc(  
	HWND hwnd,		// handle to window
	UINT uMsg,		// message identifier
	WPARAM wParam,	// first message parameter
	LPARAM lParam);	// second message parameter

int WINAPI WinMain(  
	HINSTANCE a_hInstance,		// handle to current instance
	HINSTANCE a_hPrevInstance,	// handle to previous instance
	LPSTR a_lpCmdLine,			// pointer to command line
	int a_nCmdShow)				// show state of window
{
	MSG msg;     
	WNDCLASS wc;     
	
	// register the main window class
	wc.style = 0;         					// class style
	wc.lpfnWndProc = (WNDPROC) WindowProc; 			// class window callback function
	wc.cbClsExtra = 0;         				// class extra data
	wc.cbWndExtra = 0; 					// window extra data
	wc.hInstance = a_hInstance;         			// application instance handle
	wc.hIcon = LoadIcon((HINSTANCE) NULL, IDI_APPLICATION);	// icon handle
	wc.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);	// default cursor handle
	wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); // default background brush handle
	wc.lpszMenuName =  NULL; 				// resource name for the class menu
	wc.lpszClassName = "MainWndClass";          		// class name
	if (!RegisterClass(&wc)) 
	{
		return FALSE;     
	}
	
	g_hInstance = a_hInstance;  // save instance handle      
	
	// Create the main window. 
	g_hWndMain = CreateWindow(
		"MainWndClass", 		// window class used to create the window
		"Sample", 			// caption
		WS_OVERLAPPEDWINDOW, 		// window style
		CW_USEDEFAULT, 			// x coordinate of top left corner of the window
		CW_USEDEFAULT, 			// y coordinate of top left corner of the window
        	CW_USEDEFAULT, 			// width of window
		CW_USEDEFAULT, 			// height of window
		(HWND) NULL, 			// parent window handle
        	(HMENU) NULL, 			// handle to the menu
		g_hInstance, 			// application instance
		(LPVOID) NULL);  		// pointer to CREATESTRUCT
	
	// If the main window cannot be created, terminate     
	// the application.  
	if (!g_hWndMain)         
	{
		return FALSE;
	}
	
	// Show the window and paint its contents.  
	ShowWindow(g_hWndMain, a_nCmdShow);     // display the window
	UpdateWindow(g_hWndMain);		// update the content of window immediately
	
	// Start the message loop.      
	while (GetMessage(&msg, (HWND) NULL, 0, 0)) 	// get the message from the message queue
	{         
		TranslateMessage(&msg);			// translate virtual key message to char message
		DispatchMessage(&msg);			// dispatch the message to corresponding window function
	}  
    
	// Return the exit code to Windows.      
	return msg.wParam; 
}

LRESULT CALLBACK WindowProc(  
	HWND a_hwnd,		// handle to window
	UINT a_uMsg,		// message identifier
	WPARAM a_wParam,	// first message parameter
	LPARAM a_lParam)	// second message parameter
{
	switch (a_uMsg)
	{
	case WM_DESTROY:
		PostQuiteMessage(0);
	default:
		return DefWindowProc(a_hwnd, a_uMsg, a_wParam, a_lParam);
	}
}

This is a simple Windows program that simply display one window and do nothing else. Let us analysis the program now.

<windows.h> is the main include file for Win32 SDK. Since Win32 SDK is very big, you can define WIN32_LEAN_AND_MEAN to exclude rarely used stuffs in the <windows.h>. STRICT definition instructs <windows.h> for stricter type checking. Since MFC defines it by default, define it now will make your life a lot easier if your codes will be used in other MFC projects too. For normal Windows applications, STRICT is not defined by default. (Note: the latest Platform SDK included in the MSDN subscription seems defined it by default. My library that used at work did not use it. Therefore, after I installed the Platform SDK, I spent couple hours to fix up my library.)

Let's skip couple lines. The next thing we are looking into is the function WinMain(). WinMain() is the entry point of Windows applications as opposed to main() in DOS programs. The first parameter (a_hInstance) is the an instance handle that uniquely identify your application. The second parameter (a_hPrevInstance) is not used in Win32 applications and it is always set to NULL. The third parameter (a_lpCmdLine) is the command line excluding the name of the program. The last parameter (a_nCmdShow) is a hint of how the main window should be displayed initially.

The codes inside WinMain() can be divided into 2 parts. The first part is for the main window creation. In order to create a window, you need to register your own window class. A window class is a set of attributes that Windows uses as a template to create a window in an application. After your window class is registered, you can call CreateWindow() to create the main window.

The second part is the message loop. During an application is running, there are a lot of events happening. Examples of events are mouse button clicking, mouse moving, keyboard key down, window moving, window resizing, etc, etc.... Windows format these events as messages and then store them in the application specific message queue. The GetMessage() function get the function from the message queue. Then, the message is passed to TranslateMessage() to have some keyboard messages translated. The message is finally dispatched by DispatchMessage() to corresponding window function. The window function is the one registered by the corresponding window class. If there is no message in the message queue, the GetMessage() function will block the execution of the application until a message arrived. Therefore, unused time can be allocated to other applications.

When the message reached the window function (WindowProc), you can do your own processsing for the message or pass to DefWindowProc() for default handling. In this sample, it processes only one message, WM_DESTROY. The window function calls PostQuitMessage() to put WM_QUIT message in the message queue. When GetMessage() gets the WM_QUIT, it returns FALSE and stop the message loop and finally quit the program.

Here is the super fast introduction of Windows programming. I cannot go too deep without introducing other aspects of Windows programming. Therefore, I stop here first. If you have any question related to this topic, please email me and I will try to answer it.

The source code is available here. It is a Visual C++ 5.0 project.


Professional Games/Multimedia Programming
Copyright John Wong, 1998
This page is last revised on May 18, 1998

Please send any comments on this web site to [email protected]