鼠标和键盘系统Global Hook

时间:2014-04-07 11:04:56

标签: c++ winapi c++builder

我想使用DLL在C ++中设置键盘和鼠标的全局系统挂钩。我的程序正在运行,但并不完全符合我的需要。例如,程序不会将鼠标事件挂钩到其他窗口或弹出菜单或模态对话框中。我想将鼠标和键盘事件挂钩到其他窗口,程序等所有系统鼠标和键盘事件中。我的代码有什么问题需要改变才能让它按照我的需要工作,我找不到自己出了什么问题,我按照文档中的描述做了,我需要帮助。

我使用VCL在C ++ Builder中进行编码

DLL:

#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

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

3 个答案:

答案 0 :(得分:2)

两个非常明显的问题:

  1. DLL将被注入所有其他进程。您不能指望从已连接到另一个进程的DLL调用VCL方法。您必须找到另一种报告诊断的方法。
  2. 因为您使用的是全局挂钩,所以需要处理32/64位问题。您需要生成DLL的32位和64位版本,并从32位和64位进程设置挂钩。
  3. 如果您可以使用低级别挂钩,则应考虑采用该选项。优点是没有低水平钩子的注射。您根本不需要创建DLL。

答案 1 :(得分:0)

一些评论,希望能解决您的问题:使用&#34;低级&#34;钩子(WH_MOUSE_LL,WH_KEYBOARD_LL)因为它们保证只是全局的。我觉得你的应用程序只有一个&#34; local&#34; (线程)钩。

我与CBuilder在使用钩子时创建的DLL有不好的经验。 ...即:与您描述的完全相同的问题。我建议使用Microsoft编译器重新编译DLL(并提供要使用的.DEF文件)。

您可能需要将DLL放在标识为系统目录的位置。

您不需要将SetHook放置在DLL中,这可以通过&#34; main&#34;来完成。申请也是。

答案 2 :(得分:0)

在Win 7上,您只能挂钩具有相同或更低权限的程序中的邮件。即如果您自己的程序以标准权限运行,它将永远不会看到任何针对某个进程的鼠标或键盘消息。管理员权限。 - iamjoosy