Click here to Skip to main content
13,256,716 members (51,978 online)
Click here to Skip to main content
Add your own
alternative version


185 bookmarked
Posted 7 Jun 2000

Windows Message Handling - Part 3

, 8 Jun 2000
Rate this:
Please Sign up or sign in to vote.
Handling messages in SDK programs.

Handling Messages in SDK applications

This article assumes you are familiar with creating a window in an SDK program. The Dialog part assumes you are familiar with creating modal and modeless dialog in a SDK program.

Handling messages in SDK applications is a totally different process than MFC. No ClassWizard or macros to help you. No CWinApp to implement the Message Loop for you. It's all up to you.

Windows Classes and Window Procedures

Window "classes" in traditional programming for Windows define the characteristics of a "class" (not a C++ class) from which any number of windows can be created. This kind of class is a template or model for creating windows. In Windows, every window has a Window Class that defines the attributes of a window such as the window's icon, the window's background and the window's procedure. To create a Window class, you call RegisterClass that accepts a WNDCLASS structure defining the properties of the Window class. Every window must have a window class, so typically, RegisterClass is called in WinMain.

Usually, the Message Loop is implemented as a basic while loop:

MSG msg; 
while (GetMessage (&msg, NULL, 0, 0)) 
    TranslateMessage (&msg); 
    DispatchMessage (&msg);
return msg.wParam;

The MSG structure is a structure that holds all the information about the message: The window it was sent to, the message identifier, the 2 lParam/wParam parameters that come with the message, the time at which the message was sent, and the position of the mouse when the message was sent.

The call to GetMessage tells windows to retrieve the first message in the Message Queue. If there is no message in the Message Queue, GetMessage will not return until there is. The return value from GetMessage depends on the message it retrieved: If it was a WM_QUIT message it will return FALSE, if it wasn't, it will return TRUE. The TranslateMessage function translates virtual-key messages into character messages. The character messages are posted to the calling thread's Message Queue, to be read the next time the thread calls the GetMessage function. For example, if you get a WM_KEYDOWN message, TranslateMessage will add a WM_CHAR message to your Message Queue. This is very useful because the WM_KEYDOWN will only tell you what key has been pressed, not the character itself. A WM_KEYDOWN for VK_A could mean "a" or "A", depending on the state of the Caps Lock and Shift key. TranslateMessage will do the work of checking if it should be capital for you. The call to DispatchMessage will call the Window Procedure associated with the window that received the message. That's the SDK Message Loop in a nutshell.

A Window Procedure is a function called by the Message Loop. Whenever a message is sent to a window, the Message Loop looks at the window's Window Class and calls the Window Procedure passing the message's information. A Window Procedure is prototyped as:

    HWND hwnd, // handle to window 
    UINT uMsg, // message identifier 
    WPARAM wParam, // first message parameter 
    LPARAM lParam // second message parameter 

The HWND is the handle to the window that received the message. This parameter is important since you might create more than one window using the same window class. uMsg is the message identifier, and the last 2 parameters are the parameters sent with the message.

Typically, a Window Procedure is implemented as a set of switch statements, and a call to the default window procedure:

                      WPARAM wParam, LPARAM lParam) { 
    switch (uMsg)
    case WM_CREATE: 
        //Do some initialization, Play a sound or what ever you want
        return 0 ; 
    case WM_PAINT: 
        //Handle the WM_PAINT message
        return 0 ; 
    case WM_DESTROY: 
        PostQuitMessage (0) ;
        return 0 ; 
    return DefWindowProc (hwnd, message, wParam, lParam) ; 

The switch-case block inspects the message identifier passed in the uMsg parameter and runs the corresponding message handler. The PostQuitMessage call will send a WM_QUIT message to the Message Loop, causing GetMessage() to return FALSE, and the Message Loop to halt.


As I stated in Part 1, Windows should handle any message you don't handle. The call to DefWindowProc() gives Windows a shot at the message. Some messages such as WM_PAINT and WM_DESTROY must be handled in your Window Procedure, and not in DefWindowProc.

Putting it all together: AllToGether.C

#include <windows.h>
//Declare the Window Procedure

int WINAPI WinMain(
    HINSTANCE hInstance,  // handle to current instance
    HINSTANCE hPrevInstance,  // handle to previous instance
    LPSTR lpCmdLine,      // pointer to command line
    int nCmdShow          // show state of window
    static TCHAR lpszClassName[] = TEXT ("AllTogether") ;
    HWND         hwndMainWindow ;
    MSG          msg ;
    WNDCLASS     wndclass ;
    //Fill in the Window class data
    wndclass.cbClsExtra    = 0 ;
    wndclass.cbWndExtra    = 0 ;
    // The default window background
    wndclass.hbrBackground = COLOR_WINDOW;
    // The system, IDC_ARROW cursor
    wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
    //The system IDI_APPLICATION icon
    wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
    wndclass.hInstance     = hInstance ;
    wndclass.lpfnWndProc   = WndProc ;
    //The name of the class, needed for CreateWindow
    wndclass.lpszClassName = lpszClassName;
    wndclass.lpszMenuName  = NULL ;         = CS_HREDRAW | CS_VREDRAW ;

    RegisterClass (&wndclass);
    hwndMainWindow = 
        CreateWindow (lpszClassName, // pointer to registered class name
            TEXT ("Lets Put it all together"), // pointer to window name
            WS_OVERLAPPEDWINDOW, // window style
            CW_USEDEFAULT, CW_USEDEFAULT, // position of window
            CW_USEDEFAULT, CW_USEDEFAULT, // size of window
            NULL, // handle to parent or owner window
            NULL, // handle to menu 
            hInstance, // handle to application instance
            NULL) ; // pointer to window-creation data
     ShowWindow (hwnd, nCmdShow);
     UpdateWindow (hwnd) ;
     while (GetMessage (&msg, NULL, 0, 0))
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
     return msg.wParam ;

                       WPARAM wParam, LPARAM lParam) { 
    switch (uMsg)
    case WM_CREATE: 
        //Do some initialization, Play a sound or what ever you want
        return 0 ; 
    case WM_PAINT: 
        //Handle the WM_PAINT message
        return 0 ; 
    case WM_DESTROY: 
        PostQuitMessage (0) ;
        return 0 ; 
    return DefWindowProc (hwnd, message, wParam, lParam) ; 

Sending Messages

Besides receiving messages, you will often find yourself sending messages. You might want to send messages to communicate between two windows in your program, or to communicate between different programs. In order to send a message, you need a handle to the target window. This can be retrieved using a variety of functions, including FindWindow(), GetDlgItem(), GetParent(), EnumWindows() and many more. The SDK has a SendMessage() function which allows you to send messages to a window. For example, let's say you have a handle to the Calculator, and you want to close it. What you should do is send a WM_CLOSE message, which will notify the Calculator that it should close. You can use the following code. In order to get a pointer to Calculator, I use the FindWindow() function and pass the title of the window, which in our case is "Calculator":

HWND hWndCalc;
//Get a handle to the "Calculator" Window
hWndCalc = FindWindow(NULL, TEXT("Calculator));
if(hWndCalc == NULL)
    //Couldn't find Calculator
    SendMessage(hWndCalc, WM_CLOSE, 0, 0);
    //Presto! The Calculator should close.

LOWORD and HIWORD macros: Split up lParam and wParam

Often, one or more of the 32-bit lParam and wParam parameters are actually made of two 16-bit parameters. One case is the WM_MOUSEMOVE message. MSDN states that the lParam for this message is actually 2 values: the X position of the mouse, and the Y position of the mouse. But how do you retrieve the values from the lParam? The SDK has 2 macros designed for exactly this purpose: LOWORD() and HIWORD(). The LOWORD macro retrieves the low-order word from the given 32-bit value, and the HIWORD() macro retrieves the high-order word. So, given an lParam of WM_MOUSEMOVE, you can retrieve the coordinates using the following code:

WORD xPos = LOWORD(lParam);  // horizontal position of cursor 
WORD yPos = HIWORD(lParam);  // vertical position of cursor 

MAKELPARAM and MAKEWPARAM macros: concatenate two 16-bit values

LOWORD and HIWORD are fine if you want to split up the parameters, but what if you want to create a 32-bit value for use as an lParam or wParam parameter in a message? The SDK has 2 macros for this situation also: MAKELPARAM and MAKEWPARAM both combine two 16-bit values into a 32-bit value, that is usable for messages. For example, the following code sends a WM_MOUSEMOVE message to a window (HWND hWndTarget) with the fFlags parameter as the wParam, and the x/y coordinates as the lParam:

SendMessage(hWndTarget, WM_MOUSEMOVE, fFlags, MAKELPARAM(x,y));


Handling a message in a dialog is very similar to handling a message in a normal window. Windows have Window Procedures, Dialogs have Dialog Procedures. One major difference is that you don't specify a window class for a dialog. When you create a dialog using one of the CreateDialog... functions or the DialogBox... functions, you pass a Dialog Procedure as one of the parameters. A Dialog Procedure is prototyped as:

    HWND hwndDlg,  // handle to dialog box
    UINT uMsg,     // message
    WPARAM wParam, // first message parameter
    LPARAM lParam  // second message parameter

You might have noticed that the Dialog Procedure looks very similar to the Window Procedure, but it isn't a real Window Procedure. The Window Procedure for the dialog is located inside windows. That Window Procedure calls your Dialog Procedure when various messages are sent to your window. Because of the above, there are messages that you will receive in a Window Procedure that you won't receive in a Dialog Procedure. There are a few major differences between a Window Procedure and a Dialog Procedure:

  • A Dialog Procedure returns a BOOL, a Window Procedure returns a LRESULT.
  • A Dialog Procedure doesn't need to handle WM_PAINT or WM_DESTROY.
  • A Dialog Procedure doesn't receive a WM_CREATE message, but rather a WM_INITDIALOG message
  • A Window Procedure calls DefWindowProc() for messages it does not handle. A Dialog Procedure should return TRUE if it handled the message or FALSE if not with one exception: if you set the input focus to a control in WM_INITDIALOG, you should return FALSE.

User-defined messages

Sometimes, you will need to communicate between 2 windows in your application or between 2 windows from different applications. An easy way to do this is by using User-defined messages. The name "User-defined" can be confusing at first; you define a User-defined message and not the user of your program. I have stated in Part 1 that messages are identified by numbers, and that Windows predefines standard messages. The way of using user-defined messages is to simply use a number. To make sure that you don't conflict with the system defined messages, you should use a number in the range of WM_APP through 0xBFFF:

#define WM_DELETEALL WM_APP + 0x100
SendMessage(hWndYourDialog, WM_DELETEALL, 0, 0);

You handle a user-defined message just like you handle a regular message:

#define WM_DELETEALL WM_APP + 0x100
//Window Procedure
    switch (uMsg) 
    case WM_DELETEALL:
        //We've got the user-defined message, lets Delete All
        return 0;
    case WM_CREATE: 
        //Do some initialization, Play a sound or what ever you want
        return 0 ; 
    case WM_PAINT: 
        //Handle the WM_PAINT message
        return 0 ; 
    case WM_DESTROY: 
        PostQuitMessage (0) ;
        return 0 ; 
    return DefWindowProc (hwnd, message, wParam, lParam) ; 

Registered Windows Messages

The RegisterWindowMessage function is used to define a new window message that is guaranteed to be unique throughout the system. Like user-defined messages, Registered Messages are handled like regular messages:

static UINT WM_FIND = RegisterWindowMessage(TEXT("YOURAPP_FIND_MSG");
//Window Procedure
    switch (uMsg)
    case WM_FIND:
        //We've got the registered message, lets start Finding.
        return 0;
    case WM_CREATE: 
        //Do some initialization, Play a sound or what ever you want
        return 0 ; 
    case WM_PAINT: 
        //Handle the WM_PAINT message
        return 0 ; 
    case WM_DESTROY: 
        PostQuitMessage (0) ;
        return 0 ; 
    return DefWindowProc (hwnd, message, wParam, lParam) ; 

The registered message identifiers using this approach will be in the range of 0xC000 to 0xFFFF. And you send it using the regular SendMessage() method:

static UINT WM_FIND = RegisterWindowMessage(TEXT("YOURAPP_FIND_MSG"));
SendMessage(hWndFindWindow, WM_FIND, lParam, wParam);


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Daniel Kopitchinski
Web Developer
Israel Israel
No Biography provided

You may also be interested in...

Comments and Discussions

GeneralHandling dialog's message pumping in a suppurate thread is not working Pin
Rajulife30-Nov-07 4:16
memberRajulife30-Nov-07 4:16 
GeneralGreat article Pin
zhi-chen22-Mar-07 9:42
memberzhi-chen22-Mar-07 9:42 
GeneralWindows Message Handling Pin
ng4kau15-Mar-07 18:49
memberng4kau15-Mar-07 18:49 
QuestionAre you "Daniel Kopitchinski" ? Pin
Daniel Kopitchinski1-Jan-07 22:59
memberDaniel Kopitchinski1-Jan-07 22:59 
Generalhandling mouse messages Pin
Harish N R1-Jan-07 1:46
memberHarish N R1-Jan-07 1:46 
Generalfinding the menu item name associated with handle/wParam/lParam Pin
Dr. Chuck20-Oct-06 4:27
memberDr. Chuck20-Oct-06 4:27 
GeneralDoubt in using Dialog Box Pin
codingfreak15-Nov-05 13:04
membercodingfreak15-Nov-05 13:04 
Generaldialog box Pin
imadulhaq29-Mar-05 1:37
memberimadulhaq29-Mar-05 1:37 
Generalconsole message maps.... Pin
dharani3-Sep-04 3:30
memberdharani3-Sep-04 3:30 
GeneralRe: console message maps.... Pin
David Lam13-Nov-04 22:27
memberDavid Lam13-Nov-04 22:27 
GeneralRe: console message maps.... Pin
.:floyd:.15-Jan-05 18:25
member.:floyd:.15-Jan-05 18:25 
GeneralRe: console message maps.... Pin
David Lam16-Jan-05 1:17
memberDavid Lam16-Jan-05 1:17 
QuestionRe: console message maps.... Pin
enigma183919-Jun-07 6:33
memberenigma183919-Jun-07 6:33 
QuestionSet Dialog BK color? Pin
quoi3531-Aug-04 21:39
memberquoi3531-Aug-04 21:39 
Generaltrace of v c++ Pin
Anonymous17-Jun-04 6:46
sussAnonymous17-Jun-04 6:46 
GeneralHooking using WndProc Pin
gonx19-Apr-04 14:57
membergonx19-Apr-04 14:57 
Generalhandling messages when the window is in background Pin
damartin1326-Mar-04 12:19
sussdamartin1326-Mar-04 12:19 
GeneralRegisterWindowMessage doesn't work with a case expression. Pin
Denhoff9-Dec-03 5:46
sussDenhoff9-Dec-03 5:46 
GeneralRe: RegisterWindowMessage doesn't work with a case expression. Pin
TomKat12-Feb-04 12:08
memberTomKat12-Feb-04 12:08 
GeneralRe: RegisterWindowMessage doesn't work with a case expression. Pin
Asm4pic14-Aug-06 23:59
memberAsm4pic14-Aug-06 23:59 
Error 1 error C2051: case expression not constant
should i use if-expression instead of switch-case
or there is another hint to use switch

Ahmed Samieh

QuestionHow can I get the handle to the editbox in a save dialog? Pin
C++Noob4-Oct-02 3:17
sussC++Noob4-Oct-02 3:17 
GeneralMessage Return Value in a Dialog Pin
kilowatt20-Mar-02 5:55
memberkilowatt20-Mar-02 5:55 
GeneralMessage priority Pin
FOX30-Sep-01 7:22
memberFOX30-Sep-01 7:22 
Generalsending message from 32 bit application to 16 bit application Pin
anshu21-Aug-01 0:07
memberanshu21-Aug-01 0:07 
GeneralCreateDialog Pin
Anonymous31-Mar-01 13:27
memberAnonymous31-Mar-01 13:27 
GeneralRe: CreateDialog Pin
Anonymous6-May-01 2:40
memberAnonymous6-May-01 2:40 
GeneralRe: CreateDialog Pin
Malik Bashir Ahmad5-Aug-03 1:46
memberMalik Bashir Ahmad5-Aug-03 1:46 
GeneralRe: CreateDialog Pin
Anonymous29-Oct-01 13:06
memberAnonymous29-Oct-01 13:06 
GeneralRe: CreateDialog Pin
Nitron17-May-03 17:27
memberNitron17-May-03 17:27 
GeneralHandling WM_CHAR in DlgProc :eek: Pin
niranjan11-Dec-00 19:35
memberniranjan11-Dec-00 19:35 
GeneralRe: Handling WM_CHAR in DlgProc :eek: Pin
Anonymous29-Oct-01 13:03
memberAnonymous29-Oct-01 13:03 
GeneralDon't use while(GetMessage()) Pin
Matthew Ellis12-Jun-00 8:25
sussMatthew Ellis12-Jun-00 8:25 
GeneralRe: Don't use while(GetMessage()) Pin
Daniel Kopitchinski12-Jun-00 10:40
sussDaniel Kopitchinski12-Jun-00 10:40 
GeneralRe: Don't use while(GetMessage()) Pin
suhredayan®27-Jun-05 21:36
membersuhredayan®27-Jun-05 21:36 
GeneralRe: Don't use while(GetMessage()) Pin
Daniel Kopitchinski12-Jun-00 22:00
sussDaniel Kopitchinski12-Jun-00 22:00 
GeneralRe: Don't use while(GetMessage()) Pin
Matthew Ellis13-Jun-00 3:58
sussMatthew Ellis13-Jun-00 3:58 
Generaluse while(GetMessage()) Pin
Alexander Mullins13-Jun-00 3:01
sussAlexander Mullins13-Jun-00 3:01 
GeneralRe: use while(GetMessage()) Pin
Matthew Ellis13-Jun-00 3:50
sussMatthew Ellis13-Jun-00 3:50 
GeneralRe: use while(GetMessage()) Pin
William Kempf13-Jun-00 8:08
sussWilliam Kempf13-Jun-00 8:08 
GeneralRe: use while(GetMessage()) Pin
Matthew Ellis13-Jun-00 8:46
sussMatthew Ellis13-Jun-00 8:46 
GeneralRe: use while(GetMessage()) Pin
William Kempf13-Jun-00 13:02
sussWilliam Kempf13-Jun-00 13:02 
GeneralRe: use while(GetMessage()) Pin
igor196027-Nov-01 21:45
memberigor196027-Nov-01 21:45 
GeneralRe: use while(GetMessage()) Pin
DJM8-Jan-02 1:39
memberDJM8-Jan-02 1:39 
GeneralRe: use while(GetMessage()) Pin
iacchus25-Mar-02 12:31
memberiacchus25-Mar-02 12:31 
GeneralRe: Don't use while(GetMessage()) Pin
Anonymous7-Feb-01 8:15
memberAnonymous7-Feb-01 8:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.171114.1 | Last Updated 9 Jun 2000
Article Copyright 2000 by Daniel Kopitchinski
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid