是否可以捕获messages/events
内的窗口Translate/Dispatch Message loop
?
这是窗口的消息处理方法
LRESULT CALLBACK MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_KEYDOWN:
PressedKey[wParam] = true;
break;
case WM_KEYUP:
PressedKey[wParam] = false;
break;
case WM_SIZE:
break;
default:
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
这里是Translate/Dispatch Message loop
void MyScreen::RunScreenMainLoop()
{
while (WM_QUIT != msg.message)
{
//I wanna handle the messages here as well!
switch (msg.message)
{
case WM_SIZE:
show("size event called");
break;
default:
break;
}
if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
//do other stuff
}
}
}
但是它永远不会进入switch语句,是否有一个工作要做到这一点?
答案 0 :(得分:3)
一个明显的问题似乎是您在初始化之前阅读msg.message
。请注意,在致电msg.message
之前,您正在阅读PeekMessage
。当然,由于我们无法看到msg
被宣布的位置,也许真正的代码不会遇到这个问题。
现在,主要问题是WM_SIZE
不是排队的消息,并且不通过消息队列到达。异步排队消息(如输入消息,计时器消息,绘制消息和直接传递给窗口过程的同步消息)之间存在重要区别。并且WM_SIZE
是非排队的,同步的。
您可以从documentation中了解到这一点:
窗口通过其WindowProc函数接收此消息。
你不会用GetMessage
,PeekMessage
等来捕获它。拦截此消息的方法来自窗口proc中的代码。
要了解有关排队和非排队邮件的详情,您可以从MSDN开始使用此主题:About Messages and Message Queues。
答案 1 :(得分:1)
这不是你的消息循环应该如何看。试试这个:
void MyScreen::RunScreenMainLoop()
{
MSG msg;
while (1)
{
if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
//do other stuff
}
}
}
然后通过继承这些窗口拦截特定窗口的消息:
LRESULT CALLBACK MySubWndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
switch (msg)
{
case WM_SIZE:
show("size event called");
break;
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, MySubWndProc, uIdSubclass);
break;
// other case statements as needed...
}
return DefSubclassProc(hWnd, msg, wParam, lParam); // will dispatch the message to MsgProc()
}
hWnd = CreateWindowEx(...);
SetWindowSubclass(hWnd, MySubWndProc, 0, 0);
答案 2 :(得分:0)
您编写了消息泵,因此您可以在rmessage循环中自由添加代码来处理消息。例如,如果您不希望WM_CHAR
转换,请不要致电TranslateMessage()
。 If you want normal windows to have dialog-style tab navigation, call IsDialogMessage()
. You can literally go crazy here.
线程消息以相同的方式工作。主题消息没有窗口,因此DispatchMessage()
对他们没有任何作用。你必须处理消息泵中的那些。
但是,请记住,如果您输入对话框或使用其自己的消息泵的其他内容,您的自定义将丢失。 Here's an explanation that uses thread messages.
MFC,ATL,Qt,WPF等也可能有自己的消息泵设置,你必须注意(或他们自己的消息泵,期间,在这种情况下,你必须看看API是否提供挂钩机制)。
答案 3 :(得分:0)
如果您只想循环处理邮件,只需访问MSG获取您的邮件信息,如下所示:
void MyScreen::RunScreenMainLoop()
{
while (WM_QUIT != msg.message)
{
// Handle here your messages
if (msg.message == WM_LBUTTONDOWN) // Mouse Left Button Event
{
MessageBox(NULL, L"You Clicked!", L"Info", MB_OK);
}
//
if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
//do other stuff
}
}
}