Win32 从另一线程截获窗口消息
前言
我的 C 课设被要求必须使用 EasyX,但同时我还想使用窗口菜单。
插入窗口菜单没有难度,编程方式和加载方式都可以,但问题出在处理上。由于没有回调函数,我没法处理 WM_COMMAND 消息。我尝试使用 GetMessage 和 PeekMessage 函数,但设了断点以后发现,这两个函数根本不会返回,也就是说,消息队列里一个消息都没有,这让我很苦恼,于是我查了又查,终于偶然间发现了可能解决方案。
·本文在所有关键位置插入了转至相应文档的超链接,以便参考。
问题成因
我设了一堆断点,最后发现,EasyX 有一 EasyX::GraphWnd::ThreadFunc 函数,正是该函数调用了 EasyX::GraphWnd::WndProc。从名称上看,ThreadFunc 函数应该与线程有关。由此,EasyX 所使用的线程与主函数的不一致,因此我们要通过该线程来截获窗口消息。
Hooks
终于,我发现了这个神奇的东西。一看介绍我就兴奋了:
A hook is a point in the system message-handling mechanism where an application can install a subroutine to monitor the message traffic in the system and process certain types of messages before they reach the target window procedure.
翻译:
挂钩是系统消息处理机制中的一个点,应用程序可以在该点上安装子程序,以监视系统中的消息流量并在消息到达目标窗口过程之前处理某些类型的消息。
显然,这就是我要找的那个答案。
然而,文档中有那么多可用函数类型,应该用哪个呢?
没关系,我们可以一个一个试嘛。
GetMsgProc
经过我的试验,这个最靠谱。
那我们就来吧。
#include <easyx.h>
LRESULT CALLBACK GetMsgProc(int code, WPARAM wParam, LPARAM lParam); // 前向声明
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nShowCmd)
{
HWND hWnd = initgraph(640, 480); // 我这里是 EasyX 的情况,其它情况下应该大同小异,只要获取了 hWnd 就 OK
SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, NULL, // 这里的第三个参数应当是 HINSTANCE 类型,但根据文档说明,当前代码中的 HINSTANCE 使用 NULL
GetWindowThreadProcessId(hWnd, NULL)); // 看到这里了吗?我们不能使用 GetCurrentThreadId,而应使用这个函数来获取 hWnd 的线程。
// 代码…
return 0;
}
LRESULT CALLBACK GetMsgProc(_In_ int nCode,
_In_ WPARAM wParam,
_In_ LPARAM lParam)
{
if (nCode < 0 || wParam == 0)
return CallNextHookEx(NULL, nCode, wParam, lParam); // 根据文档的内容,我们需要这样写
MSG msg = *(PMSG)lParam; // 我们需要转换一下,因为实际上只有 lParam 是我们熟悉的消息
/*然后我们就可以 switch 了!*/
switch (msg.message)
{
// 代码……
case WM_COMMAND:
switch (LOWORD(msg.wParam))
{
// 代码……
default:
break;
}
break;
default:
break;
}
return CallNextHookEx(NULL, nCode, wParam, lParam); //最后也要记得根据文档内容调用这个函数并返回哦~
}
这样我们就能处理窗口消息啦!
_
记得查看文档哦,对于 Win32 编程,查文档是很重要的
.
转载请私信,未经许可谢绝转载。