我想使用 DLL 在 C++ 中为键盘和鼠标设置全局系统 Hook 。我的程序正在运行,但并不完全符合我的需要。例如,该程序不会在其他窗口或弹出菜单或模态对话框上 Hook 鼠标事件。我想在其他窗口、程序等的任何地方 Hook 鼠标和键盘事件,所有系统鼠标和键盘事件。我的代码有什么问题需要更改什么才能使其按我的需要工作,我自己找不到问题所在,我正在按照文档中的描述进行操作,我需要帮助。
我正在使用 VCL 在 C++ Builder 中编码
动态链接库:
#include <vcl.h>
#include <windows.h>
#include "main.h"
#pragma hdrstop
#pragma argsused
typedef struct _HOOKSTRUCT
{
int nType;
HOOKPROC hkprc;
HHOOK hhook;
bool bInstalled;
} HOOKSTRUCT;
static HOOKSTRUCT hook[2];
HINSTANCE hDLL;
int nThreadCode;
bool bInit;
TForm1 *form;
extern "C" __stdcall __declspec(dllexport) LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
extern "C" __stdcall __declspec(dllexport) LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam);
//---------------------------------------------------------------------------
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
hDLL = hinst;
bInit = false;
return 1;
}
//---------------------------------------------------------------------------
extern "C" __stdcall __declspec(dllexport) void Init()
{
hook[0].nType = WH_KEYBOARD;
hook[0].hkprc = (HOOKPROC)KeyboardProc;
hook[0].bInstalled = false;
hook[1].nType = WH_MOUSE;
hook[1].hkprc = (HOOKPROC)MouseProc;
hook[1].bInstalled = false;
bInit = true;
}
//---------------------------------------------------------------------------
extern "C" __stdcall __declspec(dllexport) bool SetHook(int nHook)
{
if(!bInit)
{
Init();
}
hook[nHook].hhook = NULL;
hook[nHook].hhook = SetWindowsHookEx(hook[nHook].nType,
(HOOKPROC)hook[nHook].hkprc, hDLL, 0);
if(hook[nHook].hhook != NULL)
{
MessageBox(NULL, "Setup hook successful", "Information", MB_OK);
}
return true;
}
//---------------------------------------------------------------------------
extern "C" __stdcall __declspec(dllexport) void UnsetHook(int nHook)
{
UnhookWindowsHookEx(hook[nHook].hhook);
}
//---------------------------------------------------------------------------
extern "C" __stdcall __declspec(dllexport) LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(((DWORD)lParam&0x40000000) && (HC_ACTION==nCode))
{
if(form != NULL)
{
form->Memo1->Lines->Add("Key Pressed");
}
}
return CallNextHookEx(hook[0].hhook, nCode, wParam, lParam);
}
//---------------------------------------------------------------------------
extern "C" __stdcall __declspec(dllexport) LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{
char str[128];
PMOUSEHOOKSTRUCT Info = (PMOUSEHOOKSTRUCT)lParam;
wsprintf(str, "The mouse message at X: %d,Y: %d", Info->pt.x, Info->pt.y);
form->Memo2->Lines->Add(str);
return CallNextHookEx(hook[1].hhook, nCode, wParam, lParam);
}
//---------------------------------------------------------------------------
extern "C" __stdcall __declspec(dllexport) void SetControl(TForm1 *Object, int nApp)
{
form = Object;
nThreadCode = nApp;
}
程序:
#include <vcl.h>
#pragma hdrstop
#include "main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
HINSTANCE hInst;
typedef bool (*install)(int);
typedef void (*uninstall)(int);
typedef void (*passself)(TForm1 *, int);
install InstallHook;
uninstall UninstallHook;
passself PassThis;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
N2->Enabled = true;
N3->Enabled = true;
N4->Enabled = false;
N5->Enabled = false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
Memo1->Clear();
Memo2->Clear();
hInst = LoadLibrary("ch49dll.dll");
if(hInst == NULL)
{
ShowMessage("Load DLL error " + AnsiString(GetLastError()));
return;
}
InstallHook = (install)GetProcAddress(hInst, "SetHook");
if(InstallHook == NULL)
{
ShowMessage("Get SetHook ProcAddress Error");
return;
}
UninstallHook = (uninstall)GetProcAddress(hInst, "UnsetHook");
if(UninstallHook == NULL)
{
ShowMessage("Get UnsetHook ProcAddress Error");
return;
}
PassThis = (passself)GetProcAddress(hInst, "SetControl");
if(PassThis == NULL)
{
ShowMessage("Get SetControl ProcAddress Error");
return;
}
PassThis(this, 0);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
FreeLibrary(hInst);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::N2Click(TObject *Sender)
{
InstallHook(0);
N2->Enabled = false;
N4->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::N3Click(TObject *Sender)
{
InstallHook(1);
N3->Enabled = false;
N5->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::N4Click(TObject *Sender)
{
UninstallHook(0);
N4->Enabled = false;
N2->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::N5Click(TObject *Sender)
{
UninstallHook(1);
N5->Enabled = false;
N3->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::N7Click(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
程序头:
#ifndef mainH
#define mainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Menus.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TMemo *Memo1;
TMemo *Memo2;
TMainMenu *MainMenu1;
TMenuItem *N1;
TMenuItem *N2;
TMenuItem *N3;
TMenuItem *N4;
TMenuItem *N5;
TLabel *Label1;
TLabel *Label2;
TMenuItem *N6;
TMenuItem *N7;
void __fastcall FormCreate(TObject *Sender);
void __fastcall FormDestroy(TObject *Sender);
void __fastcall N2Click(TObject *Sender);
void __fastcall N3Click(TObject *Sender);
void __fastcall N4Click(TObject *Sender);
void __fastcall N5Click(TObject *Sender);
void __fastcall N7Click(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
所以程序可以运行并且可以 Hook 外部事件,但是对于某些对话框窗口,我的程序不会 Hook 鼠标事件。例如,当我右键单击任务栏通知区域中的图标时,将显示一个弹出窗口,如果我在弹出窗口区域中输入鼠标光标,那么我的程序将不会记录这些鼠标移动事件。另一种情况是,当我在其他程序中单击“关于程序菜单”或“关于菜单”时,将显示一个窗口,如果我将光标移到该窗口的区域内,那么我的程序将不会 Hook 鼠标和键盘的事件,为什么?如何让它卡在任何窗口的任何地方
最佳答案
两个很明显的问题:
- DLL 将被注入(inject)所有其他进程。您不能指望从已挂接到另一个进程的 DLL 调用 VCL 方法。您必须找到另一种方式来报告诊断。
- 因为您使用的是全局 Hook ,所以您需要处理 32/64 位问题。您需要生成 DLL 的 32 位和 64 位版本,并从 32 位和 64 位进程设置 Hook 。
如果您可以使用低级钩子(Hook),您应该考虑采用该选项。优点是没有低级钩子(Hook)的注入(inject)。您根本不需要创建 DLL。
关于c++ - 键鼠系统 Global Hook,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22910574/