简体   繁体   English

DestroyWindow()是否从消息队列中删除了窗口的消息?

[英]Does DestroyWindow() remove the messages for the window from the message queue?

The DestroyWindow() documentation says the following: DestroyWindow()文档说明如下:

The function also destroys the window's menu, flushes the thread message queue, 该函数还会破坏窗口的菜单,刷新线程消息队列,

Does "flushes the thread message queue" means that it will remove the messages from the message queue for the window that I want to destroy only? “刷新线程消息队列”是否意味着它将从我想要销毁的窗口的消息队列中删除消息?

Although the docs are not explicit on this, it does behave as you suggest. 虽然文档在这方面并不明确,但它确实按照您的建议行事。 Messages posted to the destroyed window are flushed and those for other windows (or posted to the thread) remain in the thread's queue. 发布到已销毁窗口的消息将被刷新,而其他窗口(或发布到该线程)的消息将保留在线程的队列中。

The following sample program demonstrates this - if your suggestion is true, no asserts should fire (and in my tests, they don't). 下面的示例程序演示了这一点 - 如果您的建议是真的,则不应该触发断言(在我的测试中,它们不会触发)。

As @HarryJohnston points out in the comments, destroying one window own by a thread does not destroy any other windows the thread owns (except for children and owned windows of the destroyed window), and so it could be quite problematic if their posted messages were removed, effectively for no reason. 正如@HarryJohnston在评论中指出的那样,通过线程销毁一个窗口并不会破坏该线程拥有的任何其他窗口(除了子窗口和被破坏窗口的拥有窗口),因此如果他们发布的消息是删除,有效无缘无故。

#include <windows.h>
#include <assert.h>  

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    assert(message != WM_APP + 1);
    return DefWindowProc(hWnd, message, wParam, lParam);
}

int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEXW wcex{};
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.lpfnWndProc = WndProc;
    wcex.hInstance = hInstance;
    wcex.lpszClassName = L"msgflushtest";
    assert(RegisterClassExW(&wcex));

    HWND hWnd = CreateWindowEx(0, L"msgflushtest", nullptr, WS_POPUP, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
        HWND_DESKTOP, nullptr, hInstance, nullptr);
    assert(hWnd);

    assert(PostMessage(hWnd, WM_APP + 1, 0, 0)); // should be flushed
    assert(PostThreadMessage(GetCurrentThreadId(), WM_APP + 2, 0, 0)); // should not be flushed

    DestroyWindow(hWnd);

    MSG msg;
    assert(!PeekMessage(&msg, nullptr, WM_APP + 1, WM_APP + 1, PM_REMOVE));
    assert(PeekMessage(&msg, nullptr, WM_APP + 2, WM_APP + 2, PM_REMOVE));

    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM