C++ 模拟键鼠详细总结

C++ 模拟键鼠详细总结,第1张

简介
  • 需要使用user32.dll,所以项目中要引入静态链接库 user32.lib
  • #include
  • 鼠标输入官方例程

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

键鼠状态查询

虚拟键码

// 获取鼠标位置
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); // 抬起
后记

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

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/793072.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-05
下一篇 2022-05-05

发表评论

登录后才能评论

评论列表(0条)

保存