Hey guys,
As part of some larger profiling and optimization work I have been looking into how I handle messages in my Win32 app. My code for handling windows messages is probably mostly copy-pasted from some tutorial or book I read many years ago (ie. I don't remember exactly) and I haven't really thought much about it until now.
So, the way I handle windows messages is to call this method every frame:
void Win32RenderWindow::messagePump()
{
MSG msg;
while(PeekMessage(&msg, mHandle.windowsHandle, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
That's pretty standard as far as I know. My window procedure looks like this:
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_CREATE)
{
// Store a pointer to the window which sent this message.
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)(((LPCREATESTRUCT)lParam)->lpCreateParams));
return 0;
}
// Get the stored window pointer by window handle.
Win32RenderWindow* window = reinterpret_cast<Win32RenderWindow*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
if(window)
return window->msgProc(msg, wParam, lParam);
else
return DefWindowProc(hwnd, msg, wParam, lParam);
}
If there is a render window, the proc forwards the call to the window. Otherwise the default proc is called. The render window method looks something like this:
LRESULT Win32RenderWindow::msgProc(UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
/* ... handle app specific messages here ... */
}
return DefWindowProc(mHandle.windowsHandle, msg, wParam, lParam);
}
Again, fairly standard stuff. Inside the switch I handle things like window resize events etc. These are some observations I have made about the system and I would like to ask about them:
- The call to Win32RenderWindow::messagePump() can sometimes take a long time (10ms or so). It might be enough to move the mouse very quickly back and forth over the render window to generate a lot of messages. Is it normal for the processing to take this long? According to my profiler the time is spent inside PeekMessage() and DefWindowProc() and almost no time is spent anywhere else.
- I always though that, under normal circumstances, the call to the message procedure (MainWndProc()) is done through the call to DispatchMessage() but it seems like PeekMessage() is calling it too, and 99% of the time spent inside MainWndProc() and is through PeekMessage() rather than DispatchMessage(). Again, is this normal?
- Why is PeekMessage() calling the window procedure at all? Isn't it just supposed to get the message of the queue and give it to you so you can handle it by calling TranslateMessage() and DispatchMessage()?
Thanks!
EDIT: After some further investigation it seems like DefWindowProc() can call back to the main window proc (This was news to me too, I did not know that could happen), which might explain why it looks like so much time is spent inside DefWindowProc().