I have the following code, see below.
Why is the code case WM_KILLFOCUS in WinMain() never reached? If I remove case WM_KILLFOCUS from WndProc(), the one in WinMain() is still not reached. Case WM_KEYDOWN works just fine.
How do I fix code so that case WM_KILLFOCUS in WinMain() is reached?
The code is pretty basic.
Thank you.
#include <windows.h>
HINSTANCE m_hinstance_Module = NULL;
HWND m_hwnd_Window = NULL;
LRESULT CALLBACK WndProc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
{
switch (umessage)
{
case WM_KILLFOCUS:
// THE CODE REACHES THIS POINT.
MessageBoxA(hwnd, "WM_KILLFOCUS", "WndProc()", 0);
return DefWindowProc(hwnd, umessage, wparam, lparam);
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_CLOSE:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, umessage, wparam, lparam);
}
// Done.
return 0;
}
void InitializeWindow()
{
WNDCLASSEX struct_WNDCLASSEX;
m_hinstance_Module = GetModuleHandle(NULL); // If this parameter is NULL, GetModuleHandle returns a
handle to the file used to create the calling process (.exe file).
struct_WNDCLASSEX.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
struct_WNDCLASSEX.lpfnWndProc = WndProc;
struct_WNDCLASSEX.cbClsExtra = 0;
struct_WNDCLASSEX.cbWndExtra = 0;
struct_WNDCLASSEX.hInstance = m_hinstance_Module;
struct_WNDCLASSEX.hIcon = LoadIcon(NULL, IDI_WINLOGO);
struct_WNDCLASSEX.hIconSm = struct_WNDCLASSEX.hIcon;
struct_WNDCLASSEX.hCursor = LoadCursor(NULL, IDC_ARROW);
struct_WNDCLASSEX.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
struct_WNDCLASSEX.lpszMenuName = NULL;
struct_WNDCLASSEX.lpszClassName = L"TEST";
struct_WNDCLASSEX.cbSize = sizeof(WNDCLASSEX);
RegisterClassEx(&struct_WNDCLASSEX);
m_hwnd_Window = CreateWindowEx(WS_EX_APPWINDOW, L"TEST", L"TEST", WS_OVERLAPPEDWINDOW, 0, 0, 800,
600, NULL, NULL, m_hinstance_Module, NULL);
ShowWindow(m_hwnd_Window, SW_SHOW);
SetForegroundWindow(m_hwnd_Window);
SetFocus(m_hwnd_Window);
}
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine,
_In_ int nShowCmd)
{
MSG structMsg;
bool blnDone = false;
InitializeWindow();
ZeroMemory(&structMsg, sizeof(MSG));
while (!blnDone)
{
if (PeekMessage(&structMsg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&structMsg);
DispatchMessage(&structMsg);
}
if (structMsg.message == WM_QUIT)
{
blnDone = true;
}
else
{
switch (structMsg.message)
{
case WM_KILLFOCUS:
// THE CODE NEVER REACHES THIS POINT.
MessageBoxA(m_hwnd_Window, "WM_KILLFOCUS", "WinMain()", 0);
break;
case WM_KEYDOWN:
MessageBoxA(m_hwnd_Window, "WM_KEYDOWN", "WinMain()", 0);
break;
}
}
}
return 0;
}
Message routing is done using either of two methods:
The system uses two methods to route messages to a window procedure: posting messages to a first-in, first-out queue called a message queue, a system-defined memory object that temporarily stores messages, and sending messages directly to a window procedure.
Messages that are posted to the message queue are called queued messages, whereas messages that are immediately passed to a window procedure are called nonqueued messages.
WM_KILLFOCUS
is a nonqueued message1. That's why the window procedure observes this message, while the message loop does not.
This is an architectural limitation. You cannot make nonqueued messages show up in the message queue.
1 The hint is encoded in the documentation: "Sent to a window", as opposed to "posted".