C++ 模拟键鼠详细总结

简介

下面这些操作,一定要看官方文档,这样能少走很多弯路。

键鼠状态查询

虚拟键码

// 获取鼠标位置
POINT p;
GetCursorPos(&p);
qDebug() << "cur mouse:" << p.x << "," << p.y;
// 判断鼠标左键是否被按下
if((GetAsyncKeyState(VK_LBUTTON)& 0x8000)? 1:0){
    qDebug()<<"lbutton down";
}
// 判断 K 是否被按下
if((GetAsyncKeyState(0x4B)& 0x8000)? 1:0){
    qDebug()<<"k down";
}

GetKeyState和GetAsyncKeyState的区别

GetAsyncKeyState就是检查在调用该函数时,某一key的状态。而GetKeyState是检查window message发生时,某一key的状态。

如果在MSG产生的时候,Ctrl是没有按下的;而在调用GetAsyncKeyState的那一刻,Ctrl是按下的。那么GetAsyncKeyState会通知你Ctrl是按下的。反之通知你Ctrl是没有按下的。
如果在MSG产生的时候,Ctrl是按下的,那么GetKeyState会通知你Ctrl是按下的。反之通知你Ctrl是没有按下的。与调用GetKeyState那一刻Ctrl的状态是没有关系的。

虚拟键码与扫描码

MapVirtualKeyW,该函数可用于虚拟键码和扫描码之间的转换

// 返回结果为翻译结果
UINT WINAPI MapVirtualKeyW(   
  _In_  UINT uCode,    // 扫描码或虚拟键码
  // 0: 虚拟键码->扫描码
  // 1: 扫描码->虚拟键码
  _In_  UINT uMapType
);

扫描码:键盘硬件对应的按键的编码;虚拟键码:操作系统对应的按键的编码;
当用户按下某个按键时:
1)键盘会检测到这个动作,并通过键盘控制器把扫描码(scan code) 传送到计算机; 键盘扫描码跟具体的硬件有关的,不同厂商对同一个键的扫描码有可能不同。  
2)计算机接收到 扫描码 后,将其交给键盘驱动程序;
3)键盘驱动程序 把这个 扫描码转换为键盘虚拟码;虚拟码与具体硬件无关,不同厂商的键盘,同一个键的虚拟码总是相同的。
4)然后,键盘驱动程序 把该键盘操作的 扫描码和虚拟码以及其它信息传递给 操作系统;操作系统将获得 的信息封装在一个键盘消息中,并把该键盘消息插入到消息列队。
5)通过Windows的消息系统,该键盘消息被送到某个窗口中;
6)窗口所在的应用程序接收到消息后,可以了解到有关 键盘操作的信息,然后决定作出一定的响应。

控制键鼠

  • 官网已不建议使用 mouse_event函数 了,但是,mouse_event 使用起来比 SendInput 方便,且不会被360限制(我测试的时候,发现SendInput 会被360杀毒拦截。。。)
  • 官网建议使用 SendInput 函数,它集成了键鼠的所有操作

我使用SendInput没成功,所以大家如果想用它的话,请参考官方文档。我这里介绍 mouse_event 和 keybd_event 两个函数来实现相应的操作

mouse_event

官方文档

void mouse_event(
  [in] DWORD     dwFlags, // 操作类型
  [in] DWORD     dx, // 相对或绝对的移动量
  [in] DWORD     dy, // 相对或绝对的移动量
  [in] DWORD     dwData, // 如果有滚轮事件则代表滚轮的变化量,可正负,一圈为120(WHEEL_DELTA),如果没有滚轮事件,该值应当设为0
  [in] ULONG_PTR dwExtraInfo // 给0就行
);

可用的操作类型参考官方文档,里面写的很详细,这里提供简单的案例。

// 模拟鼠标左键
mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);
Sleep(50);
mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);

keybd_event

官方文档
虚拟键码

void keybd_event(
  [in] BYTE      bVk, // 虚拟键码
  [in] BYTE      bScan, // 一般设置为0即可,可以用 MapVirtualKeyW(虚拟键码值,0)得到
  [in] DWORD     dwFlags, // 具体的事件,0代表按下,KEYEVENTF_KEYUP代表松开
  [in] ULONG_PTR dwExtraInfo // 一般设置为0即可
);

// 模拟按键K
keybd_event(0x4B,MapVirtualKeyW(0x4B,0),0,0); // 按下
Sleep(50);
keybd_event(0x4B,MapVirtualKeyW(0x4B,0),KEYEVENTF_KEYUP,0); // 抬起

后记

写这篇文章的时候,我已经走了很多弯路,所以为让大家少走弯路,我把这些经验总结了一下,有许多内容是来自官方文档或者别的博客,由于看的内容比较碎,我也忘了是来源于哪个博客了,感谢各位博主的探索。

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值