关于钩子的基本用法和设置请参考C++技术网《钩子最基本的设置方法(作者:NBHZ200)》,在此不作赘述。
通过捕获WM_COMMAND消息的思想来实现。由于Windows中每个进程都有自己独立的地址空间,因此对新菜单的响应代码并不能放在我们所编写程序的exe(称为控制程序)中,而是要放在dll内。dll中代码如下:
#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#define IDM_TEST 0x100//菜单ID
extern HMODULE hDll;//包含钩子过程的dll应用实例句柄,可通过DllMain函数的第一个参数获取;也可通过函数GetModuleHandle获取
#pragma data_seg(".shared")
HWND g_hWnd = 0;//窗口句柄
HMENU hMenu=0; //窗口菜单
HHOOK g_hHook=0; //HOOK句柄
UINT WM_HOOKSPY=0; //自定义消息,通知远程进程读取编辑框控件的内容
#pragma data_seg()
#pragma comment(linker,"/SECTION:.shared,RWS")
#define pCW ((MSG*)lParam)
extern "C" LRESULT CALLBACK HookProc(
int code,
WPARAM wParam,
LPARAM lParam
)
{
if(code>=0)
{
if(pCW->message==WM_COMMAND)//捕获WM_COMMAND消息
{
if(LOWORD(pCW->wParam)==IDM_TEST)//wParm低16位控件ID号,高16位为通知码
{
MessageBox(NULL,_T("test"),_T("NotepadHook"),0);
}
UnhookWindowsHookEx(g_hHook);
}
}
return CallNextHookEx(g_hHook,code,wParam,lParam);
}
_declspec(dllexport) void NotepadHook()
{
g_hWnd=FindWindow(_T("Notepad"),_T("无标题 - 记事本"));//获取记事本窗口句柄
hMenu=GetMenu(g_hWnd);//获取菜单
AppendMenu(hMenu,MF_ENABLED | MF_STRING,IDM_TEST,_T("testMenu"));//在菜单中添加新菜单testMenu
DrawMenuBar(g_hWnd);
g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)HookProc,
hDll,GetWindowThreadProcessId(g_hWnd,NULL));//安装钩子
}
我们所编写的控制程序代码:
void CNotepadDlg::OnClickedAppend()
{
typedef void (*NotepadHook)();
NotepadHook notepadhook=NULL;
HINSTANCE hDll=0;
hDll=LoadLibrary(_T("NotepadHook.dll"));
notepadhook=(NotepadHook)GetProcAddress(hDll,"?NotepadHook@@YAXXZ");
if(NULL==notepadhook)
MessageBox(_T("error"));
notepadhook();
}
结果分析:调试运行时,钩子能够安装成功,菜单也能添加成功,但当菜单按下时没有任何反应。通过SPY++查看,菜单按下时会发送WM_COMMAND消息,而且其ID也和设定的一致。找了好久资料和相关知识,但还是不知道问题出在哪个环节,欢迎能和大神们探讨!