鼠标模拟软件






4.91/5 (14投票s)
一个简单的基于软件的鼠标模拟器
您可以在这里找到本文的俄语版本
如何实现
引言
本项目演示了使用编程钩子技术通过键盘来模拟鼠标。鼠标模拟软件在“真实”鼠标损坏(或不存在)并且您需要执行一些需要鼠标指针设备的操作时非常有用。
背景
有一天,在旧电脑上工作时,我遇到了一个问题……USB端口坏了,并且没有PS/2鼠标。我决定编写一个简单的程序来代替鼠标设备。
Using the Code
“虚拟鼠标”软件的思路如下。 首先,需要选择并分配键以对应鼠标动作。 选择的分配如下
- 向左移动指针(NUM4)
- 向右移动指针(NUM6)
- 向上移动指针(NUM8)
- 向下移动指针(NUM5)
- 鼠标左键单击(NUM7)
- 鼠标右键单击(NUM9)
这些分配的源代码如下所示
// keys to control cursor
#define KeyMoveLeft VK_NUMPAD4
#define KeyMoveRight VK_NUMPAD6
#define KeyMoveUP VK_NUMPAD8
#define KeyMoveDown VK_NUMPAD5
// keys to emulate mouse buttons
#define KeyClickLeft VK_NUMPAD7
#define KeyClickRight VK_NUMPAD9
另一件必要的事情是分配一个按钮(它可以是按键的组合),该按钮将控制“虚拟鼠标”的状态。 如有必要,可以将其打开和关闭。 为此,代码中存在以下定义
// key to switch on/off MouseEmulate software
#define KeyMouseEmulateEnDis VK_F7
接下来的显而易见的动作是
- 创建用于按键处理的函数
- 从“
main
”函数启动键盘钩子
什么是键盘钩子? 钩子是一种机制,应用程序可以通过该机制拦截事件,例如消息,鼠标动作和击键。 拦截特定类型事件的函数称为钩子过程。 钩子过程可以作用于其接收的每个事件,然后修改或丢弃该事件[1]。 要启动键盘钩子,必须编写在按下键时将处理的回调函数。 回调函数是
LRESULT CALLBACK KeyboardHook (int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HC_ACTION)
if (wParam == WM_SYSKEYDOWN || wParam == WM_KEYDOWN ||
wParam == WM_SYSKEYUP || wParam == WM_KEYUP)
CheckKey (nCode, wParam, lParam);
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
在此,CheckKey(…)
函数正是“键处理器”。 此函数的内容(骨架)如下所示
void CheckKey( int nCode, WPARAM wParam, LPARAM lParam )
{
…
// switch on/off the MouseEmulate program
if (wParam == WM_SYSKEYUP || wParam == WM_KEYUP)
{
if( hookStruct->vkCode == KeyMouseEmulateEnDis )
{
bEmulEn = bEmulEn ? false: true;
}
}
if(bEmulEn)
{
switch ( hookStruct->vkCode )
{
case KeyClickLeft:
{
// emulating left mouse button click
}
break;
case KeyClickRight:
{
// emulating right mouse button click
}
break;
case KeyMoveLeft:
{
// move cursor left
}
break;
case KeyMoveUP:
{
// move cursor up
}
break;
case KeyMoveRight:
{
// move cursor right
}
break;
case KeyMoveDown:
{
// move cursor down
}
break;
}
}
}
可以从“main
”函数启动钩子
int APIENTRY WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHook, hInstance , 0);
while (GetMessage(NULL,NULL,0,0)) ; // NOP while not WM_QUIT
return UnhookWindowsHookEx(hHook);
}
有关函数SetWindowsHookEx(…)
的更多详细信息,请参见[2]。
最好使用确定移动光标的步长值的技术,具体取决于是否长按(或短按)负责移动光标的按钮。 以下函数负责该想法
void StepCalculate()
{
unsigned short speedMax = 40;
unsigned short dt = tNow-tBefore;
float dtMax = 30.0f;
step = (int)(speedMax * dtMax/(tNow-tBefore));
}
在此,speedMax
变量是通过长按键动作移动光标时的最大步长(40像素)。 dt
值表示两个相同的按键(长按键被视为多次按键)之间的时间差。
技巧
要使此软件每次Windows启动时都运行,只需将“.exe”文件放入“启动”目录中即可。
在文本编辑器中使用此软件时,请按下CTRL按钮以避免输入意外的char
值。
关注点
我第一次编写此软件时,将鼠标左键单击模拟为“向左移动光标”-“向右移动光标”键的快速单击组合。 鼠标右键单击也类似地模拟为“向右移动光标”-“向左移动光标”键的单击组合。 这非常好,但是仍然存在一些错误。 很高兴将来实现(或恢复)这样的想法。
参考文献
- http://msdn.microsoft.com/en-us/library/ms644959(v=vs.85).aspx
- http://msdn.microsoft.com/en-us/library/ms644990(v=vs.85).aspx
历史
- 2011年5月10日:初始版本