An Introduction to Messages

Messages are at the heart of Windows GUI programming. Almost everything a GUI program does is triggered by messages. Messages are tied to events, and the program must be ready to respond to any of them at any given time.
    The primary message handlers are the window procedures. Messages can be sent or posted. When a message is sent, a window procedure is invoked and the sender waits for it to complete before proceeding further. When a message is posted, it goes into a message queue and the poster proceeds without waiting. Posted messages are retrieved with GetMessage or PeekMessage. GetMessage is usually a part of a message loop that invokes window procedures via DispatchMessage.
    Windows produces a lot of messages, but the typical application will provide a custom response to only a small percentage of them. Most of the messages can be classified as notifications--"this happened" or "this is about to happen" messages. A few messages, e.g., WM_PAINT, can be interpreted as commands.
    [See More on Messages.]

The example program

Our example program, window03.asm, responds to left and right mouse button clicks by changing the title bar. Below, we show what's different from the basic GUI program.

Titles

We define two titles and set up our window to display one of them on startup. The window width is made long enough to avoid clipping of the title text.
DEFAULT_STYLE equ WS_VISIBLE + WS_OVERLAPPED + WS_CAPTION + WS_SYSMENU + \
                  WS_THICKFRAME + WS_MINIMIZEBOX + WS_MAXIMIZEBOX 
DEFAULT_EXSTYLE equ WS_EX_WINDOWEDGE + WS_EX_CLIENTEDGE 
DEFAULT_X  equ 100 
DEFAULT_Y  equ 100 
DEFAULT_WIDTH equ 400 
DEFAULT_HEIGHT equ 200 

    .data 

    align 4 

cwargs CREATEARGS <DEFAULT_EXSTYLE,wndclsname,title1,DEFAULT_STYLE, \
          DEFAULT_X,DEFAULT_Y, DEFAULT_WIDTH,DEFAULT_HEIGHT, 0,0, 0, 0> 
title1 db 'Left-click to change title',0 
title2 db 'Restore title by right-clicking',0

Dispatch

The following is one way to dispatch messages. It's not bad because there are so few messages. A bigger set of messages would be easier to handle with an address table.
    Each message handler uses exactly the same argument list block (we could call it the message packet) as WndProc.
    extrn DefWindowProc:near 

    .code
WndProc:
    mov    eax,[esp+4+4]      ; message ID
    cmp    eax,WM_LBUTTONDOWN ; left mouse button pressed
    je     left_mouse_down
    cmp    eax,WM_RBUTTONDOWN ; right mouse button pressed
    je     right_mouse_down
    cmp    eax,WM_DESTROY     ; about to start window destruction
    je     start_destroy
    jmp    DefWindowProc      ; delegate other message processing

Mouse messages

This is how we respond to the mouse messages. The selected title depends on which button is pressed. The code is left unoptimized so that it shows more clearly where the hwnd parameter is coming from. (The +4 skips the stacked EIP, and +0 is the offset of the first argument.)
    extrn  SetWindowText:near 

    .code
left_mouse_down: 
    mov    eax,[esp+4+0] ; get hwnd before changing ESP 
    push   offset title2 
    push   eax 
    call   SetWindowText 

    xor    eax,eax 
    ret    16 

right_mouse_down: 
    mov    eax,[esp+4+0] ; get hwnd before changing ESP 
    push   offset title1 
    push   eax 
    call   SetWindowText 

    xor    eax,eax 
    ret    16