gpt4 book ai didi

c++ - WM_QUIT 只发布线程而不是窗口?

转载 作者:可可西里 更新时间:2023-11-01 12:47:19 27 4
gpt4 key购买 nike

在 Windows API 中,我正在研究 GetMessage 函数的实际工作原理。我已经看到了 Windows 消息循环的 3 个实现,并且想探索它们。


1)

截至撰写本文时,this MSDN article描述了我认为是实现消息循环的正确方法。

MSG msg;
BOOL bRet;
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}


2)

关于 GetMessage function page ,我看到了这个实现:

MSG msg;
BOOL bRet;
while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}


3)

最后,Visual Studio documentation将此实现作为其 Win32 应用程序演示的一部分。

MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}


讨论

简而言之,实现 #3 忽略了从 GetMessage 返回的错误,但在其他方面与第一个实现相同。也就是说,它们都处理当前线程的所有消息。当 GetMessage 函数返回 0 时,循环终止。

因为我在 #1 之前找到了实现 #2,所以我认为它已经完成了。但是,我注意到当通过 PostQuitMessage 发布 WM_QUIT 消息时,GetMessage 不会返回 0

这导致了一些困惑,直到我找到实现 #1 并对其进行了测试。前两个实现的区别在于 GetMessage 的第二个参数。在 #2 中,它指定了 hWnd,根据 GetMessage 文档,它是:

A handle to the window whose messages are to be retrieved. The window must belong to the current thread.

在 #1 中,它是 NULL,属于此摘录:

If hWnd is NULL, GetMessage retrieves messages for any window that belongs to the current thread, and any messages on the current thread's message queue whose hwnd value is NULL (see the MSG structure). Therefore if hWnd is NULL, both window messages and thread messages are processed.

当使用NULL进行测试时,GetMessage函数在处理完WM_QUIT消息时返回0,成功终止循环。

问题

  1. 即使 PostQuitMessage 是从特定窗口的回调函数调用的,WM_QUIT 是否真的属于该窗口或当前线程?根据对这三个实现的测试,它似乎与当前线程相关联。

  2. 如果与线程关联,何时使用有效的hWnd 作为GetMessage 的参数有用或合适?这样的消息循环将无法返回 0 作为对 WM_QUIT 的 react ,那么有没有其他方法可以终止消息循环?

引用资料

代码

#include <Windows.h>
#include <tchar.h>
#include <strsafe.h>

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int nCmdShow) {
LPCTSTR wndClassName =_T("Class_SHTEST");
LPCTSTR wndName = _T("SHTest");

WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW|CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
wcex.hbrBackground = (HBRUSH) COLOR_WINDOW+1;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = wndClassName;
wcex.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));

if (!RegisterClassEx(&wcex))
{
MessageBox(NULL, _T("Call to RegisterClassEx failed!"), wndName, MB_OK|MB_ICONERROR);
}

HWND window = CreateWindow(wndClassName, wndName,
WS_OVERLAPPEDWINDOW | WS_MAXIMIZE,
0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
if (!window) {
MessageBox(NULL, _T("Call to CreateWindow failed!"), wndName, MB_OK|MB_ICONERROR);
}

ShowWindow(window, SW_SHOW);
UpdateWindow(window);

//Message loop (using implementation #1)
MSG msg;
BOOL bRet;
while((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
if (bRet == -1) {
//Handle error and possibly exit.
}
else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

//Return the exit code in the WM_QUIT message.
return (int) msg.wParam;
}

最佳答案

根据 MSDN documention WM_QUIT:

The WM_QUIT message is not associated with a window and therefore will never be received through a window's window procedure. It is retrieved only by the GetMessage or PeekMessage functions.

由于 WM_QUIT 不与窗口相关联,并且将 HWND 传递给 GetMessage() 仅检索与该窗口相关联的那些消息,后者在设计上永远不会收到 WM_QUIT

至于何时您希望将 HWND 传递给 GetMessage(),在应用程序的一般消息循环中您不会这样做。但有时您希望在 UI 中发生某些事情时发送消息,并且只关心与特定窗口关联的消息。

关于c++ - WM_QUIT 只发布线程而不是窗口?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32768924/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com