开发平台:VC6.0

基于MFC

玩游戏的时候,经常遇到想用手柄但游戏本身不支持的事儿。这样的情况下,我们就要使用软件,将手柄映射为键盘,以达到目的。网上有几款比较流行的优秀的此类软件,比如JoyToKey,Xpr等。这些软件方便实用,都很成熟。不过它们都有一点小瑕疵,就是无法将一键映射为多键。听这句话可能有些朋友迷糊了,JoyToKey不就能吗,你怎么说不能吗。如果您这样想,那么您肯定是误会我的意思了。JoyToKey提供的一键映多键功能是按下手柄的一个键,相当于同时按下了键盘上的多个键,在这里,我所说的映多键,是指在手柄上设定一个辅助键。按住和松开辅助键时,按其他键会分别映射成键盘上的不同键。类似于键盘的shift的效果,但注意,不是直接映射为shift,对大多数游戏而言,字母大小写识别为一样。

前述结束,那么我们就开始说正题。

一个手柄/键盘映射程序,无外乎就四部分:一、界面;二、接收;三、处理;四、输出。

界面就不多说了。

接收,就是接收手柄的输出。这部分有多种方法,比如windows API和DirectX,这里我们选前者。

处理,就是将接收到的数据映射为输出数据。

输出,就是向操作系统发送假的键盘事件,从而完成映射过程。

接收部分:

那么,我们先来进行知识的准备。为了完成接收部分,我们需要了解和手柄相关的windows API。其中常用的较重要的函数如下:

joyGetDevCaps                  查询指定的游戏杆设备以确定其性能

joyGetNumDevs                  返回系统支持的游戏杆设备的数量

joyGetPos                       查询指定的游戏杆设备的位置和活动性

joyGetPosEx                    查询一个游戏杆设备的位置和它的按扭状态

joyGetThreshold                查询指定的游戏杆设备的当前移动阈值

joyReleaseCapture              释放由JoySetCapture函数设置的在指定游戏杆设备上的捕获

joySetCapture                  发送一个游戏杆消息到指定的窗口

joySetThreshold                设置指定的游戏杆设备的移动阈值

要使用这几个API,需要连接winmm.lib,包含mmsystem.h头文件。如下图所示:

如果仅制作基本的映射功能,那么我们并不需要用到全部的函数。主要使用的是这个:

MMRESULT joyGetPosEx(UINT uJoyID, LPJOYINFOEX pji) 

这个函数可以主动取得游戏杆信息。

参数uJoyID是指手柄的ID,对于单手柄编程,填写JOYSTICKID1即可。

参数pji是一个指向JOYINFOEX型结构体的指针。JOYINFOEX的定义如下:

typedef struct joyinfoex_tag {

    DWORD dwSize;     /* size of structure */

    DWORD dwFlags;       /* flags to indicate what to return */

    DWORD dwXpos;                /* x position */

    DWORD dwYpos;                /* y position */

    DWORD dwZpos;                /* z position */

    DWORD dwRpos;     /* rudder/4th axis position */

    DWORD dwUpos;     /* 5th axis position */

    DWORD dwVpos;     /* 6th axis position */

    DWORD dwButtons;             /* button states */

    DWORD dwButtonNumber;        /* current button number pressed */

    DWORD dwPOV;                 /* point of view state */

    DWORD dwReserved1;

    DWORD dwReserved2;

} JOYINFOEX, *PJOYINFOEX, NEAR *NPJOYINFOEX, FAR *LPJOYINFOEX;

它包含了指定手柄当前的状态信息。我们主要用到的是其中的dwFlags,dwXpos,dwYpos以及dwButtons。这四个成员依次表示:获取状态,十字键X轴当前状态,十字键Y轴当前状态,功能键当前状态。

我们在使用joyGetPosEx获得手柄状态前,先要把dwFlags设置为JOY_RETURNALL,即返回全部按键状态,这样才能同时获得十字键和功能键的信息。

dwXpos和dwYpos的值分别代表了X轴和Y轴当前的状态。对于使用windows默认的自带手柄驱动的,按键情况和对应值如下:

上下 左右
0x0000
0x7eff 不按 不按
0xffff
0x7fff 同时 同时

注意:如果安装了手柄驱动盘,值会随驱动不同而改变,请自行测定

而dwButtons的每一位对应手柄的一个功能键状态,0表示抬起状态,1表示按下状态。(注意,是状态,不是动作)对应关系是从低位到高位对应功能键1至手柄功能键最高数。

joyGetPosEx函数的返回值可能是以下几种:

/* joystick error return values */

#define JOYERR_NOERROR  (0)                /* no error */

#define JOYERR_PARMS    (JOYERR_BASE+5)  /* bad parameters */

#define JOYERR_NOCANDO  (JOYERR_BASE+6)  /*request not completed */

#define JOYERR_UNPLUGGED (JOYERR_BASE+7) /*joystick is unplugged */

根据它,我们可以判断电脑当前否有手柄连接。

输出部分:

键盘模拟部们,我们只需要使用一个很简单的函数keyevent

void keybd_event(BYTE bVk,BYTE bScan,DWORD dwFlags,DWORD dwExtralnfo);

参数:   

bVk:定义一个虚拟键码。键码值必须在1~254之间。   

bScan:定义该键的硬件扫描码。   

dwFlags:定义函数操作的名个方面的一个标志位集。应用程序可使用如下一些预定义常数的组合设置标志位。   

  KEYEVENTF_EXETENDEDKEY:若指定该值,则扫描码前一个值为OXEO(224)的前缀字节。   

  KEYEVENTF_KEYUP:若指定该值,该键将被释放;若未指定该值,该键交被接下。

  (其实就是一个是0一个是2,0表示键按下,1表示键弹起) 

dwExtralnfo:定义与击键相关的附加的32位值。

表面上看着好像很点乱,其实没那么复杂。

给一个使用实例:

#define KEY 要模拟的键的ASCII码keybd_event(KEY,MapVirtualKey(KEY, 0),0,0);

注意,这里使用MapVirtualKey()函数是有必要的。对于很多游戏,单纯的使用keybd_event(KEY,0,0,0)的模式是不能被正确识别的,换句话说,游戏程序会把那些伪造的键盘信息过滤掉或根本不接受。但使用MapVirtualKey()后,大部分游戏就会识别到我们发送的键盘信息了。

未完待续

下篇内容:编程实战

转载于:https://www.cnblogs.com/qyit/archive/2011/11/21/2257687.html

基于windows API的手柄/键盘映射编程(一)相关推荐

  1. c语言删除文件 Windows,基于Windows API实现遍历所有文件并删除的方法

    本文实例讲述了基于Windows API实现遍历所有文件并删除的方法.分享给大家供大家参考.具体分析如下: 最近一直在学windows API,弄了一些好玩的东西(有点恶作剧了,请大家谨慎使用)... ...

  2. 基于Windows api手柄映射编程

    转:https://www.cnblogs.com/qyit/archive/2011/11/21/2257687.html 一个手柄/键盘映射程序,无外乎就四部分:一.界面:二.接收:三.处理:四. ...

  3. C#低级Windows API钩子拦截键盘输入

    一. 简介 猫和婴儿有很多共同之处.他们都喜欢吃家中养植的植物,都非常讨厌关门.他们也都爱玩弄你的键盘,结果是,你正发送给你的老板的电子邮件可能是以半截句子发送出去的,你的Excel帐户也被加入了一些 ...

  4. 基于Windows API的VC++串口通信详解

    在Win32下,可以使用两种编程方式实现串口通信,其一是使用ActiveX控件,这种方法程序简单,但欠灵活.其二是调用Windows的API函数,这种 方法可以清楚地掌握串口通信的机制,并且自由灵活. ...

  5. Windows API(非MFC)编程加载位图

    很久都没写博客了,前段时间ACM那些题都是有空的时候水着玩的,虽然大二的课只有6门,但是作业很多,也一直很忙,刚刚都才完成一个电路设计的实验报告.准备TOEFL,GRE,还要跟着导师做计算机视觉的一些 ...

  6. windows api学习笔记-键盘钩子

    DLL项目的头文件 #ifdef KEYHOOKLIB_EXPORT //此宏将在CPP文件中定义 #define KEYHOOKLIB_API __declspec(dllexport) #else ...

  7. 网络编程(3)—— 基于Windows系统的socket服务器端的编程步骤

    socket服务器端编程的基本步骤: 1.1 准备Windows服务器端开发环境 导入ws2_32.lib静态连接库,项目属性->配置属性->链接器->输入->附加依赖项中添加 ...

  8. 26、Windows API Shell编程(2)

    二.文件协助(File Associations) File Associations可以指定Shell在显示.处理特定文件类型的文件时的方式,包括如下几个方面: ◇双击文件时,哪个应用程序应该被用来 ...

  9. VC串口通信(Windows API)

    本文转载自基于Windows API的VC++串口通信详解,以下附上大白的理解. 简介 在Win32下,可以使用两种编程方式实现串口通信,其一是使用ActiveX控件,这种方法程序简单,但欠灵活.其二 ...

最新文章

  1. 异步方法顺序调用问题
  2. No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=arm64, VALID_ARCHS=armv7 armv7s)
  3. 由神经网络的迭代次数计算输出值并评价网络性能
  4. complete checkbox in Fiori
  5. Win7系统隐藏文件恢复的方法
  6. Android setBackgroundResource和setBackgroundDrawable和用法
  7. Linux下如何发现内存泄漏问题(测试角度)
  8. [OpenGL] opengl常见问题汇总
  9. kNN算法__手写识别——基于Python和NumPy函数库
  10. DataRow[] /数组转换datatable!
  11. Linux检查服务器cpu状态脚本,Linux服务器硬件运行状态及故障邮件提醒的监控脚本分享...
  12. 电脑硬盘数据丢失后怎么恢复?硬盘数据恢复技巧教程
  13. 深度完美 XP SP3 完美优化DVD装机版 V2013
  14. 计算机excel柱状图刻度单位,如何设置excel图表的坐标刻度和单位-excel 柱状图 坐标 区间刻度...
  15. IDEA显示树状目录结构
  16. oneAPI 、DPC++ 学习篇章
  17. 分数之和(分子分母同分相加)
  18. jQuery封装的表单验证,模仿网易或者腾讯登录的风格
  19. JAVA I GATECH EDX
  20. 华北理工大学迁安学院计算机专业分数线,华北理工大学2018年各专业录取分数线...

热门文章

  1. windows防火墙端口设置
  2. python分段计算居民水费多少钱一吨_出租屋1.2元1度电,水费4元一吨,一个月要多少钱?...
  3. angular2 表格打印 -essence-ng2-print插件
  4. java自定义类创建数组_java 创建自定义数组
  5. docker初学小结
  6. 解放双耳、放下手机,Sanag A11S秘境寒鸦气传导耳机体验
  7. 小程序touchmove事件中setData优化过程
  8. 中国Java之父张孝祥去世------给it人士的思考
  9. Oracle19c 创建表空间
  10. 英伟达开源深度学习加速器介绍