2017-03-02 133 views
2

DestroyWindow()文档说以下内容:DestroyWindow()从消息队列中删除窗口的消息吗?

功能也破坏了窗口的菜单,刷新线程 消息队列,

是否“刷新线程消息队列”意味着它将从消息队列中删除我只想销毁的窗口的消息?

+0

该手册页说“摧毁相关的孩子或拥有的窗户”,因此引发它也破坏了他们的消息队列。但是,操作系统检查其他每个进程,以查明和重新组织消息队列将是荒谬的。这就像扔球,然后说,哦,不,忘记了:在它降落之前赶上它,因为我现在离场了。 –

+1

好问题,文档中没有说明。我的猜测是,只会为发布到该窗口及其子窗口的消息刷新队列。 –

+2

@WeatherVane,消息队列属于*线程*,而不是*窗口* - 单个线程可以创建多个窗口,并且还可以接收不与任何窗口关联的消息,因此销毁特定窗口不可能破坏线程的消息队列。 –

回答

3

尽管文档没有明确说明这一点,但其行为与您的建议相同。发布到销毁窗口的消息被刷新,其他窗口(或发布到该线程)的消息保留在线程的队列中。

下面的示例程序演示了这一点 - 如果你的建议是真的,没有断言应该触发(并在我的测试中,他们不)。

正如@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; 
} 
+0

这个简单的扩展(第二个窗口)表明,在这种情况下行为是相同的 - 未被销毁的窗口的消息既不会被分派也不会从队列中移除。 –

+0

(是'wcex {}'一个错字或一些新的语法,我还没有涉及?VS2010拒绝它。) –

+0

@HarryJohnston - 没有错字。新的语法。旧的'CL'编译器不理解它。但是我们可以编写'WNDCLASSEXW wcex = {};'这可以正常工作。几乎所有通常写入'WNDCLASSEXW wcex = {0};'但这里的'0'超出 - 我们可以用'= {}'用任何'CL'和'{}'(无=)从零开始初始化结构版本 – RbMm