- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
在 Windows API 中,我正在研究 GetMessage
函数的实际工作原理。我已经看到了 Windows 消息循环的 3 个实现,并且想探索它们。
截至撰写本文时,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);
}
}
关于 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);
}
}
最后,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
,成功终止循环。
即使 PostQuitMessage
是从特定窗口的回调函数调用的,WM_QUIT
是否真的属于该窗口或当前线程?根据对这三个实现的测试,它似乎与当前线程相关联。
如果与线程关联,何时使用有效的hWnd
作为GetMessage
的参数有用或合适?这样的消息循环将无法返回 0
作为对 WM_QUIT
的 react ,那么有没有其他方法可以终止消息循环?
GetMessage
PostQuitMessage
WM_QUIT
Message #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/
我是一名优秀的程序员,十分优秀!