Reputation: 466
WndProc
is the window procedure of the main window. ChildProc
is the window procedure of the child window. ChildProc
is not receiving WM_DESTROY
. What am I doing wrong?
EDIT: If I remove the WS_CHILD
window style from hChild = CreateWindowExW(...);
so it's hChild = CreateWindowExW(..., WS_VISIBLE, ...);
I do get WM_DESTROY
in ChildProc
.
Also, I'm using Windows 10 and Visual Studio 2008
#include <windows.h>
HINSTANCE g_hInst;
LRESULT CALLBACK ChildProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_PAINT:
{
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint(hwnd, &ps);
if(hdc)
{
RECT rc;
GetClientRect(hwnd, &rc);
SetBkMode(hdc, TRANSPARENT);
FillRect(hdc, &rc, GetSysColorBrush(COLOR_GRAYTEXT));
TextOut(hdc, 0, 0, TEXT("Child"), 5);
EndPaint(hwnd, &ps);
}
}
break;
case WM_DESTROY:
MessageBoxW(0, L"Child WM_DESTROY", 0, MB_OK);
break;
default:
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static HWND hChild;
switch(msg)
{
case WM_CREATE:
{
WNDCLASSEXW wc;
SecureZeroMemory(&wc, sizeof(WNDCLASSEXW));
wc.cbSize = sizeof(WNDCLASSEXW);
wc.hCursor = LoadCursorW(0, IDC_ARROW);
wc.hInstance = g_hInst;
wc.lpfnWndProc = ChildProc;
wc.lpszClassName = L"Childclass////";
if(!RegisterClassExW(&wc)) return -1;
hChild = CreateWindowExW(0, L"Childclass////", 0, WS_VISIBLE | WS_CHILD,
0, 0, 200, 100, hwnd, 0, g_hInst, 0);
if(!hChild) return -1;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEXW wc;
HWND hwnd;
MSG msg;
SecureZeroMemory(&wc, sizeof(WNDCLASSEXW));
wc.cbSize = sizeof(WNDCLASSEXW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hCursor = LoadCursorW(0, IDC_ARROW);
wc.hIcon = LoadIconW(0, IDI_APPLICATION);
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = L"Mainclass";
if(!RegisterClassExW(&wc)) return 0;
g_hInst = hInstance;
hwnd = CreateWindowExW(0, L"Mainclass", L"Main window", WS_OVERLAPPEDWINDOW, 240, 240, 400, 200, 0, 0, hInstance, 0);
if(!hwnd) return 0;
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessageW(&msg, 0, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return (int)msg.wParam;
}
Upvotes: 0
Views: 1544
Reputation: 33784
when you call DestroyWindow
(assume with valid window handle) - all child windows of course will be destroyed. and all child windows of course received WM_DESTROY
ChildProc is not receiving
WM_DESTROY
.
this is false. i absolute sure it receive it.
What am I doing wrong?
debug diagnostic and call PostQuitMessage
from wrong place.
you decide that ChildProc is "not receiving" WM_DESTROY
only because you not view message box. but it will be just closed, even before shown, if you call PostQuitMessage(0);
before it.
when a window is being destroyed WM_DESTROY
is sent first to the owned windows (if any), then to window being destroyed and finally to the child windows (if any).
so in case you use child window - first parent window received WM_DESTROY
and you call PostQuitMessage
then child window call MessageBox
which just returned without show due previous PostQuitMessage
call.
if you use owned window - it receive WM_DESTROY
first and show MessageBox
normal. and only after you close it parent window receive WM_DESTROY
finally and you call PostQuitMessage
for fix this, at first need call PostQuitMessage
from WM_NCDESTROY
- the parent window receive this message after all owned and child windows.
at second the MessageBox
not the best for debug diagnostic. much better use DbgPrint
, OutputDebugString
or breakpoints in debugger
thank @RemyLebeau for link to Raymond Chen blog - why MessageBox() does not show anything if PostQuitMessage()
was already called beforehand:
The other important thing about modality is that a
WM_QUIT
message always breaks the modal loop.
So, if PostQuitMessage()
is called before MessageBox()
, the latter will receive the WM_QUIT
message, cancel its UI, re-post WM_QUIT
, and exit.
Upvotes: 2