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