Reputation: 522797
I am in the process of developing a Windows Visual C++ application which will monitor the message pump for various events. Here is a skeleton of my main cpp file:
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow) {
HWND hwnd;
WNDCLASSEX wincl;
// register WindowProcedure() as message callback function
wincl.lpfnWndProc = WindowProcedure;
// assign other properties...
if (!RegisterClassEx (&wincl))
return 0;
// create main window
hwnd = CreateWindowEx ( ... );
// infinite message loop
while (GetMessage (&messages, NULL, 0, 0)) {
TranslateMessage(&messages);
DispatchMessage(&messages);
}
return 0;
}
And here is a skeleton of the callback function:
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch(message) {
case WM_CLIPBOARDUPDATE:
// handle the update here
}
}
My simple question is whether callback functions are guaranteed to start and end in sequence, or is it possible that they might execute in parallel with some overlapping? In other words, is it possible that 2 calls to the callback function could be executing in parallel, possibly leading to a race condition? Or does Windows guarantee that each message is handled in serial, one at a time? Any documentation or references you might provide would be welcome.
Upvotes: 3
Views: 1678
Reputation: 2890
Window messages are sometimes stored on the message queue, and sometimes they are not. Examples of window messages not stored on the queue are WM_ACTIVATE, WM_SETFOCUS and WM_SETCURSOR. Other messages, like WM_PAINT, are placed on the message queue.
A window's window procedure is never called in parellel (see previous answer).
The messages are indeed handled in a sequence and GetMessage pulls the first message from the queue. One important thing to note however is that messages can "disappear" from the queue without being processed. For example, windows internally maintains a structure (PAINTSTRUCT) for each window in which it keeps track of the window's invalid region. As soon as any part of the window's client area is invalidated windows places a WM_PAINT message on the message queue. However, if the invalid region is validated (with for example a call to ValidateRect) Windows actually removes the message from the queue. Also, if another region was added to the invalid region Windows does not place another WM_PAINT message on the queue, it updates the already placed WM_PAINT message with the updated region.
Upvotes: 1
Reputation: 6678
Window messages are stored in a queue. Everytime you call GetMessage, it removes the first message from the queue. Your window procedure is called when you call DispatchMessage.
So yes, messages are handled in sequence. However, there is some overlapping possible if inside your window procedure you call SendMessage, as that function bypasses the message queue and just calls your window procedure directly (as opposed to PostMessage which just puts the message in the queue).
But that doesn't mean the window procedure will execute in parallel (as in, from multiple threads). Neither DispatchMessage nor SendMessage will create a different thread to run the window procedure.
Upvotes: 4