c++ - 键鼠系统 Global Hook

标签 c++ winapi c++builder

我想使用 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

enter image description here

所以程序可以运行并且可以 Hook 外部事件,但是对于某些对话框窗口,我的程序不会 Hook 鼠标事件。例如,当我右键单击任务栏通知区域中的图标时,将显示一个弹出窗口,如果我在弹出窗口区域中输入鼠标光标,那么我的程序将不会记录这些鼠标移动事件。另一种情况是,当我在其他程序中单击“关于程序菜单”或“关于菜单”时,将显示一个窗口,如果我将光标移到该窗口的区域内,那么我的程序将不会 Hook 鼠标和键盘的事件,为什么?如何让它卡在任何窗口的任何地方

最佳答案

两个很明显的问题:

  1. DLL 将被注入(inject)所有其他进程。您不能指望从已挂接到另一个进程的 DLL 调用 VCL 方法。您必须找到另一种方式来报告诊断。
  2. 因为您使用的是全局 Hook ,所以您需要处理 32/64 位问题。您需要生成 DLL 的 32 位和 64 位版本,并从 32 位和 64 位进程设置 Hook 。

如果您可以使用低级钩子(Hook),您应该考虑采用该选项。优点是没有低级钩子(Hook)的注入(inject)。您根本不需要创建 DLL。

关于c++ - 键鼠系统 Global Hook,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22910574/

相关文章:

c# - delphi 导入具有指定入口点的dll函数

c++ - char 数组末尾的奇怪字符

c++ - 如何在 C++ 中进行特殊排序?

c++ - 结构节点与 std::list< >

winapi - 如何在我的应用程序中嵌入 NetLimiter

c++ - 为什么需要为每个操作系统重新编译 C/C++?

c++ - 变量改变它的值

c++ - 工作线程中的 GDI 打印机设备上下文随机失败

c++ - C++Builder6 中的 Random_shuffle 替代方案

delphi - C++ Builder/Delphi 2010 应用程序 list 模板