Reputation: 466
I get strange window painting after I send WM_NCDESTROY
manually. This only happens when visual styles are on. When 'Classic style' is on it does not seem to affect the window. I do not pass WM_NCDESTROY
to DefWindowProc()
when I send it manually, but the window still gets painted strangely. It seems like SendMessage()
is processing WM_NCDESTROY
. Why is WM_NCDESTROY
getting processed even though I do not pass it to DefWindowProc()
?
#include <windows.h>
HINSTANCE g_hInst;
LRESULT CALLBACK WndProc2(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static BOOL bProcessMsg = FALSE;
switch(msg)
{
case WM_RBUTTONUP:
SendMessage(hwnd, WM_NCDESTROY, 0, 0);
//Size window manually after this message is processed to see the effects
break;
case WM_DESTROY:
bProcessMsg = TRUE;
break;
case WM_NCDESTROY:
if(!bProcessMsg) return 0;
MessageBox(0, L"Message processed", 0, MB_OK);
return DefWindowProc(hwnd, msg, wParam, lParam);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
LRESULT CALLBACK WndProc1(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_MBUTTONUP:
{
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(WNDCLASSEX);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = g_hInst;
wc.lpfnWndProc = WndProc2;
wc.lpszClassName = L"Testclass2";
if(!RegisterClassEx(&wc)) return 0;
CreateWindowEx(0, L"Testclass2", L"Test2", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 40, 40, 200, 200, hwnd, 0, g_hInst, 0);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc = { 0 };
HWND hwnd;
MSG msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc1;
wc.lpszClassName = L"Testclass";
if(!RegisterClassEx(&wc)) return 0;
g_hInst = hInstance;
hwnd = CreateWindowEx(0, L"Testclass", L"Test1", WS_OVERLAPPEDWINDOW, 0, 0, 200, 200, 0, 0, hInstance, 0);
if(!hwnd) return 0;
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&msg, 0, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
Before right clicking on Test2
After right clicking on Test2
Upvotes: 0
Views: 120
Reputation: 942119
The WM_NCDESTROY message is rather special, it is guaranteed to be the last message that a window ever receives before it is destroyed. It is generated by the DestroyWindow() function.
Being last gives it a rather exalted status. It signals "stop doing what you've been doing". For example, you always use it when you subclass a window; this message tells you to stop subclassing it. And you'd always use it in a C++ wrapper class for a window, where it tells you when the C++ object needs to be destroyed. And it is pretty likely to be the notification that the Visual Styles renderer uses to stop making a window look different because it isn't around anymore.
Oops.
Messages like that are notifications that something interesting happened. As opposed to the kind of messages that are intended to make something interesting happen, like WM_LBUTTONDOWN, WM_KEYDOWN, WM_COMMAND. Most obvious in the WM_CLOSE vs WM_DESTROY message. WM_CLOSE is "please close the window". You can monkey with that and refuse to close the window, traditionally with the "Data not saved, are you sure" message. WM_DESTROY is "it is closed". That's a rock, it really did get destroyed, no point in ever monkeying with that one.
If you generate a fake notification, then you should be prepared to get a fake outcome. Don't mess with the important ones.
Upvotes: 5