references:
excellent post
Message
windows message is just integers
#define WM_INITDIALOG 0x0110
#define WM_COMMAND 0x0111
#define WM_LBUTTONDOWN 0x0201
....
messages are often used to communicate between windows
event like keyboard typing, mouse moving, etc will trigger the system send a message to correspond window
if you're the target window, you'll need to handle the message
every message may have 2 param bound with it, wParam and lParam, wParam->16bit, lParam->32bit, they both are 32bit in win32
these 2 param not always be used, depends on message kind
PostMessage
and SendMessage
can be used to send message
PostMessage
will puts message into Message Queue
and returns immediately, which means in the time PostMessage
returns, the message send by it may or may not been processed
while SendMessage
sends message directly to the target window, and will not return until the message been processed
for example, if we want to close a window, we can do this:
SendMessage(hwnd, WM_CLOSE, 0, 0);
Dialog
to control dialog box, you can do this:
hwnd = GetDlgItem(...);
SnedMessage(hwnd, message, ...);
or just this:
SendDlgItemMessage(...);
Message Queue
let's say you are busy on handling WM_PAINT message, at the same time, user types keyboard, what should happen now?
interrupt your drawing or drop the keys that user just input?
either are good solution, so message queue born, when message posted, they are added to message queue and they will not be removed until be handled
this will make sure every message is handled
Message Loop
while(GetMessage(&Msg, NULL, 0, 0) > 0) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
GetMessage
will retrieve message from message queue, if the queue is empty, it will simply block until there is a message- event triggers message being added to message queue,
GetMessage
will return a positive value to indicate that there is a message to be processed, theMsg
pointer point to a message structureMSG
, this structure will be filled byGetMessage
, if the message retrieved isWM_QUIT
, then 0 is returned, return negative value to indicate there is an error occurred - message retrieved by
GetMessage
will be past toTranslateMessage
as a param, this function will translate virtual key message to character message - then we pass the translated message to
DispatchMessage
, it will check which window the message is for and looks up windowproc for this window, then it will calls the founded windowproc and sending window handle, message and w/lParam as param to this proc - windowproc is your code, you need to check the message and related params, then do whatever you want! If you're not handling the message, you can just call
DefWindowProc
to perform default actions (which often means doing nothing) - after you finish message processing, your windowproc returns to
DispatchMessage
, then you back to the message loop
this is very important concept for windows programming, your windowsproc is not magically called by system, in fact, you're calling your own code indirectly from DispatchMessage
function
if you want, you can use GetWindowLong
with the window handle that the message is for to lookup your windowproc code and call it directly, without calling DispatchMessage
while(GetMessage(&Msg, NULL, 0, 0) > 0) {
WNDPROC fWndProc = (WNDPROC)GetWindowLong(Msg.hwnd, GWL_WNDPROC);
fWndProc(Msg.hwnd, Msg.message, Msg.wParam, Msg.lParam);
}
PostQuitMessage
will terminate the message loop, this function put a WM_QUIT
to the message queue
here is a demo project you can play with