返回
顶部

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, the Msg pointer point to a message structure MSG, this structure will be filled by GetMessage, if the message retrieved is WM_QUIT, then 0 is returned, return negative value to indicate there is an error occurred
  • message retrieved by GetMessage will be past to TranslateMessage 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