C++用钩子模仿按键精灵录制键盘鼠标的功能

时间:2022-11-02 00:32:46

最近需要做个跟按键精灵类似的软件,模仿键盘鼠标的动作,然后重播一次,最开时候的时候用键盘钩子和鼠标钩子做的,虽然实现了功能,但是鼠标移动速度非常快,所以换成WH_JOURNALPLAYBACK 和WH_JOURNALRECORD 钩子来做


WH_JOURNALPLAYBACK 
使应用程序可以插入消息到系统消息队列。可以使用这个Hook回放通过使用WH_JOURNALRECORD Hook记录下来的连续的鼠标和键盘事件。只要WH_JOURNALPLAYBACK Hook已经安装,正常的鼠标和键盘事件就是无效的。
是全局Hook,它不能象线程特定Hook一样使用。 WH_JOURNALPLAYBACK Hook返回超时值,这个值告诉系统在处理来自回放Hook当前消息之前需要等待多长时间(毫秒)。这就使Hook可以控制实时事件的回放。
是system-wide local hooks,它们不会被注射到任何行程位址空间。


WH_JOURNALRECORD 
用来监视和记录输入事件。典型的,可以使用这个Hook记录连续的鼠标和键盘事件,然后通过使用WH_JOURNALPLAYBACK Hook来回放。


具体原理就是定义两个全局钩子 一个用来记录 一个用来回放 话不多说 看代码

void CKMHookDll::InstallHook(bool bIsKeyDown,bool bIsMouseDown,bool bIsMouseMove/*HWND hwnd*/)
{
if (!m_pVecAction->empty())
{
m_pVecAction->clear();
}
m_bIsKeyDown = bIsKeyDown;
m_bIsMouseDown = bIsMouseDown;
m_bIsMouseMove = bIsMouseMove;
m_hRecHook = SetWindowsHookEx(WH_JOURNALRECORD,(HOOKPROC)RecHook,m_hInst,0);
}

这段代码会开启WH_HOURANLRECORD钩子,会记录键盘 鼠标事件 我把它们保存在vector中,

钩子过程如下

LRESULT CALLBACK RecHook(int code,WPARAM wParam,LPARAM lParam)
{

static int recOK = 1;
if(code<0)
{
return CallNextHookEx(CKMHookDll::GetInstance()->GetRecHook(),code,wParam,lParam);
}
else if(code==HC_SYSMODALON)
{
recOK = 0;
}
else if(code==HC_SYSMODALOFF)
{
recOK = 1;
}
else if(recOK && (code==HC_ACTION))
{
EVENTMSG action = *(EVENTMSG*)lParam;

CKMHookDll::GetInstance()->AddEvent(action);
}
return 0;
}
每个键盘 鼠标事件都被保存在vector中,等待回放,开启回放的钩子代码如下

void CKMHookDll::RunScript()
{
m_nPlayedEvent = 0;
m_hPlayHook = SetWindowsHookEx(WH_JOURNALPLAYBACK,(HOOKPROC)PlayHook,m_hInst,0);
}


回调过程如下:

LRESULT CALLBACK PlayHook(int code,WPARAM wParam,LPARAM lParam)
{
static BOOL fDelay;
static int playOK = 1;
if(code<0)
{
return CallNextHookEx(CKMHookDll::GetInstance()->GetPlayHook(),code,wParam,lParam);
}
else if(code==HC_SYSMODALON)
{
playOK = 0;
}
else if(code==HC_SYSMODALOFF)
{
playOK = 1;
}
else if(playOK && (code==HC_GETNEXT))
{
if(fDelay)
{
fDelay = FALSE;
return 50;
}
*((EVENTMSG*)lParam) = CKMHookDll::GetInstance()->GetVecAt(CKMHookDll::GetInstance()->GetPlayedEvent());
}
else if(playOK && (code==HC_SKIP))
{
fDelay = TRUE;
CKMHookDll::GetInstance()->IncPlayedEvent();
}
if(CKMHookDll::GetInstance()->GetPlayedEvent()>=CKMHookDll::GetInstance()->GetVecSize())
{
UnhookWindowsHookEx(CKMHookDll::GetInstance()->GetPlayHook());
}
return 0;
}


整个工程下载:

http://download.csdn.net/detail/mrxiao95/9471394