Menu
Win32 Tutorials

Win32

Message Loop



Tutorials > Win32 > Message Loop

View Full Source

Introduction

In the last tutorial, we learnt how to create windows. You will have noticed in the previous tutorial that the window appeared and then suddenly disappeared. This is because no messages being sent to the window were processed. All messages were sent to the DefWindowProc procedure.

This tutorial will be built upon the last. We will deal with what needs to be changed.

Contents of main.cpp :


Firstly we need to create a function that will be used to process windows messages. The signature may remind you of the extremely long WinMain function. We'll explain each part separately below.

An LRESULT is a signed result of message processing. This is what is returned from the function.

CALLBACK is a calling convention for callback functions. This is similar to the WINAPI macro which is used as a calling convention for system functions. A callback function is something that is called periodically by the application. You usually need to specify a function pointer to a function.

HWND hwnd - This is the handle to the window that received the message.

UINT msg - This is the message that was received. There are too many messages to display below so we'll name a few that will be used in the near future. Any other messages encountered in future tutorials will be explained when they are reached.

Message Description
WM_ACTIVATE Message sent when window is activated.
WM_CLOSE Message sent when the window is closed.
WM_CREATE Message sent when window is created.
WM_DESTROY Message sent when window is destroyed.

A WPARAM and a LPARAM are both message parameters. These give extra information on the messages received. These are different for every message and will be discussed when the messages are discussed.

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
			WPARAM wParam, LPARAM lParam)
{

We use a switch statement to check what message has been received.

	switch(msg)
	{

When the close button is pressed, we want to destroy the window. This can be done by using the DestroyWindow function. This function takes one parameter, being the handle to the window you want to destroy.

	case WM_CLOSE :
		DestroyWindow(hwnd);
		break;

When you use the DestroyWindow function, it sends a WM_DESTROY message. When this occurs, we want to send a quit message to our application to exit the program. The PostQuitMessage can be used to achieve this. This function takes one parameter, being the return code you wish to use. We pass 0 as no error has occurred.

	case WM_DESTROY :
		PostQuitMessage(0);
		break;
	}

Any other message not processed must be passed onto the DefWindowProc function. The function takes the same parameters passed onto our WndProc function.

	return DefWindowProc(hwnd, msg, wParam, lParam);
}

One change we have to make is to point our lpfnWndProc variable in the WNDCLASSEX structure to our new WndProc function instead of the DefWindowProc.

	wc.lpfnWndProc = WndProc;

After showing the window, we need to add what is called the message loop, this is used to catch messages and pass them onto our WndProc function.

First we need to declare a MSG variable. This is used to hold the message that has been caught by the window.

	MSG msg;

To find out what the last message received was, we can use the GetMessage function. The parameters for the function are given below.

LPMSG lpMsg - After the function call, the parameter passed onto here will contain the message that was received.

HWND hwnd - This is used to specify what window the message must be retrieved for. If a NULL is passed, a message for any window will be retrieved.

UINT wMsgFilterMin & UINT wMsgFilterMax - This specifies the range of messages to receive. Each message has an integer value so you can specify exactly what messages you want to receive. If you pass 0 for both parameters, all messages are received.

The return value is 0 if a WM_QUIT message has been received. If the return value is less than 0, some error has occurred. We only want to continue if there was no error and if there is no quit message. Remember that we caused a quit message to be sent if the window was closed.

When the GetMessage function is called, the function halts until a message is received. If you do not want this, you can use the PeekMessage function which doesn't halt, even if there was no message. This is usually used if you are busy computing something else. If you go through the OpenGL or DirectX tutorials, you will use this.

	while (GetMessage(&msg, NULL, 0, 0) > 0)
	{

2 Functions are required to send the message onto the WndProc function.

First we use the TranslateMessage function. The translate message function translates virtual-key messages into character messages which is needed. This function takes one parameter, being the MSG variable containing the message received.

		TranslateMessage(&msg);

The next function we need to use is the DispatchMessage function. This sends the message through to the window procedure (WndProc). It also takes one MSG parameter.

		DispatchMessage(&msg);
	}

Above we used the PostQuitMessage function and passed the value of 0. This could have been a different value we had passed so we cannot just return 0 as normal. We return the msg.wParam value which is the return code passed onto the PostQuitMessage function.

	return (int)msg.wParam;

Congratulations. You should now be able to process simple windows messages. If you run the program, you will notice that the window will stay on the screen until you close the window. This will destroy the window and close the program efficiently.

Please let me know of any comments you may have : Contact Me

Source Files : Visual Studio Dev-C++

< Tutorial 05 - Creating Windows Tutorial 07 - Keyboard Input >

Back to Top


All Rights Reserved, © Zeus Communication, Multimedia & Development 2004-2005

Read the Disclaimer

Links