ChildProc
是主窗口的窗口过程。 ChildProc
是子窗口的窗口过程。 WM_DESTROY
未收到WS_CHILD
。我做错了什么?
编辑:如果我从hChild = CreateWindowExW(...);
移除hChild = CreateWindowExW(..., WS_VISIBLE, ...);
窗口样式,那么WM_DESTROY
我会在ChildProc
中获得#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;
}
。
此外,我正在使用Windows 10和Visual Studio 2008
to_dict
答案 0 :(得分:2)
当你调用DestroyWindow
时(假设有效窗口句柄) - 所有子窗口当然都会被销毁。当然,所有子窗口都收到WM_DESTROY
ChildProc未收到
WM_DESTROY
。
这是假的。我绝对相信它会收到它。
我做错了什么?
调试诊断并从错误的地方呼叫PostQuitMessage
。
您认为ChildProc是&#34;没有收到&#34; WM_DESTROY
只是因为您没有查看消息框。但如果您在之前致电PostQuitMessage(0);
,它就会被关闭,即使在展示之前也是如此。
当一个窗口被销毁时WM_DESTROY
首先发送到拥有的窗口(如果有的话),然后发送到窗口被销毁,最后发送到子窗口(如果有的话)。
所以如果您使用子窗口 - 收到WM_DESTROY
的第一个父窗口并且您调用PostQuitMessage
,那么之前返回的子窗口调用MessageBox
没有显示,因为之前的PostQuitMessage
调用
如果您使用拥有的窗口 - 它会先收到WM_DESTROY
并显示MessageBox
正常。只有在您关闭之后,父窗口才会收到WM_DESTROY
,然后您致电PostQuitMessage
要解决此问题,首先需要从PostQuitMessage
拨打WM_NCDESTROY
- 父窗口会在所有拥有和子窗口之后收到此消息。
第二个MessageBox
不是调试诊断的最佳选择。更好地在调试器中使用DbgPrint
,OutputDebugString
或断点
感谢@RemyLebeau链接到Raymond Chen博客 - why MessageBox()在事先已调用PostQuitMessage()
时没有显示任何内容:
关于模态的另一个重要的事情是
WM_QUIT
消息 总是打破模态循环。
因此,如果在PostQuitMessage()
之前调用MessageBox()
,后者将收到WM_QUIT
消息,取消其用户界面,重新发布WM_QUIT
,然后退出。