如何在自己开发的程序中使用游戏手柄驱动程序或相关的游戏设

1426人阅读
编程杂项(49)
游戏手柄(JoyStick)编程学习笔记(1)
最近我开发的一个项目中需要用手柄控制一个二维移动平台的运动,找了些工业用的操作杆,感觉都挺丑的。后来想到打游戏时用的游戏手柄就挺漂亮,就决定试试用游戏手柄作为控制手柄来用。
上网查了查,在 WINDOWS 下编程控制游戏手柄比较主流的技术是用 DirectInput。如果不需要复杂的控制功能,也可以直接使用 WIN API (multimedia joystick API)。这篇学习笔记就采用 WIN API 的方式。
游戏手柄有点像是鼠标和键盘的混合体,既可以用来改变位置信息,也有一系列的按键。在 windows 系统中,是通过一个系统服务来实时监控游戏手柄的状态的。这个系统服务最多可以同时监控两个游戏手柄,每个游戏手柄最多可以有四个控制键。我们在程序中既可以直接读取游戏手柄的位置信息和按键状态,也可以通过监控相应的系统消息的方式来获得游戏手柄的信息。多数时候我们在程序中都采用接收游戏手柄消息的方式,因为这种方式不需要定时轮询游戏手柄的状态。
游戏手柄相关的函数都封装在 Winmm.dll 中。相应的头文件是 Mmsystem.h, 链接时需要链接 Winmm.lib。
查询游戏手柄信息
查询游戏手柄信息主要有三个函数。在介绍这三个函数之前需要先介绍 2 个 结构体:JOYINFO 和 JOYINFOEX。
typedef struct {
} JOYINFO;
JOYINFO 比较简单, wXpos、yXpos、zXpos 分别返回当前的坐标位置。wButtons 返回当前是否有按键按下了。 JOYINFO 结构体支持四个按键。分别是下面这四个:
JOY_BUTTON1
表示按下了第一个按键。
JOY_BUTTON2
表示按下了第二个按键。
JOY_BUTTON3
表示按下了第三个按键。
JOY_BUTTON4
表示按下了第四个按键。
我试了下,其实 JOYINFO 也是支持 32 个按键的。
如果有多个按键被按下了,那么 wButtons 的值就是这几个按键的值的或运算。
typedef struct joyinfoex_tag {
DWORD dwButtonN
DWORD dwPOV;
DWORD dwReserved1;
DWORD dwReserved2;
} JOYINFOEX;
这个结构体扩充了 JOYINFO。支持最多 6 个轴的位置信息和最多 32 个按键。
dwSize 为这个结构体的字节数,调用 joyGetPosEx 函数时需提前设置这个值。
dwFlags 为不同的值时 joyGetPosEx 函数通过这个结构体返回不同的信息。
JOY_RETURNX dwXpos 返回 X 轴的位置信息。
JOY_RETURNY dwXpos 返回 Y 轴的位置信息。
JOY_RETURNZ dwXpos 返回 Z 轴的位置信息。
JOY_RETURNR dwXpos 返回 R 轴的位置信息。
JOY_RETURNU dwXpos 返回 U 轴的位置信息。
JOY_RETURNV dwXpos 返回 V 轴的位置信息。
JOY_RETURNBUTTONS dwButtons 返回按键信息。
JOY_RETURNPOV dwPOV 返回 POV 信息。
JOY_RETURNPOVCTS dwPOV 返回 POV 信息, 100 表示 1 度。
JOY_RETURNALL 返回所有信息。
JOY_RETURNRAWDATA 返回所有信息(游戏手柄的原始信息)。
理解了这两个结构体后就可以学习这个函数了。
* \brief 获取当前计算机中有多少游戏手柄。
* \return 返回当前计算机中有多少游戏手柄。
UINT joyGetNumDevs(void);
\brief 获取指定的游戏手柄的状态信息。最多只支持三轴游戏手柄,每个游戏手柄支持 4 个按键。
\param [in] uJoyID 游戏手柄的 ID,如果只有一个游戏手柄就是 JOYSTICKID1
\param [inout] pji 指向一个 JOYINFO 的指针,通过它返回游戏手柄的位置信息和按键信息
\return JOYERR_NOERROR 表示成功返回。 MMSYSERR_NODRIVER 表示没有加载游戏手柄驱动程序。MMSYSERR_INVALPARAM 表示传入的参数有误。JOYERR_UNPLUGGED 表示指定的游戏手柄没有接入系统。
MMRESULT joyGetPos(UINT uJoyID, LPJOYINFO pji);
\brief 获取指定的游戏手柄的状态信息。
\param [in] uJoyID 游戏手柄的 ID,如果只有一个游戏手柄就是 JOYSTICKID1
\param [inout] pji 指向一个 JOYINFOEX 的指针,通过它返回游戏手柄的位置信息和按键信息,传入时需提前填好 dwSize 和 dwFlags 的值,否则函数调用会失败。
\return JOYERR_NOERROR 表示成功返回。 MMSYSERR_NODRIVER 表示没有加载游戏手柄驱动程序。MMSYSERR_INVALPARAM 表示传入的参数有误。MMSYSERR_BADDEVICEID 表示传入的 uJoyID 不合法。JOYERR_UNPLUGGED 表示指定的游戏手柄没有接入系统。
MMRESULT joyGetPosEx(UINT uJoyID, LPJOYINFOEX pji);
因为 joyGetPos 函数能支持 32 个按键,所以一般是用不到 joyGetPosEx 函数的。
下面是个简单的代码片段:
UINT wNumDevs, wDeviceID;
BOOL bDev1Attached, bDev2A
if((wNumDevs = joyGetNumDevs()) == 0)
return ERR_NODRIVER;
bDev1Attached = joyGetPos(JOYSTICKID1, &joyinfo) != JOYERR_UNPLUGGED;
bDev2Attached = wNumDevs == 2 && joyGetPos(JOYSTICKID2,&joyinfo) !=
JOYERR_UNPLUGGED;
if(bDev1Attached || bDev2Attached)
wDeviceID = bDev1Attached ? JOYSTICKID1 : JOYSTICKID2;
return ERR_NODEVICE;
这个例子很简单,先用 joyGetNumDevs() 函数判断有多少个游戏手柄。之后获得游戏手柄的当前状态。
确定游戏手柄一切正常之后就可以开始监听游戏手柄的消息了。默认情况下,WINDOWS 系统是不监控游戏手柄的,所以需要调用 joySetCapture 函数通知相应的系统服务将游戏手柄的状态改变以消息的形式传给我们的应用程序。接收消息的窗口的 HWND 需要作为第一个参数传给 joySetCapture 函数,最后一个参数如果为 FALSE 时就会不停的发送消息,即使游戏手柄的状态没有变化。
下面是代码片段:
if(wNumDevs & 0)
joySetThreshold(JOYSTICKID1, 10000);
joySetCapture((HWND)this-&winId(), JOYSTICKID1, NULL, TRUE);
剩下就是消息处理了。只有三个相应的消息类型:MM_JOY1MOVE, MM_JOY1BUTTONDOWN 和 MM_JOY1BUTTONUP。这里有两点需要注意:
MM_JOY1BUTTONDOWN 和 MM_JOY1BUTTONUP 消息只能对应游戏手柄的前四个按键,其他的按键按下是不会发消息的。但是如果按着其他的按键的同时也按下了这四个按键之一,那么我们是可以读出哪些按键被一起按下了的。
在我的电脑上所有的消息都会连着发两遍。不知道在其他的电脑上会怎么样。
下面简单介绍一下这三个消息:
MM_JOY1MOVE:对应的是摇杆的位置发生改变。
fwButtons = wP
xPos = LOWORD(lParam);
yPos = HIWORD(lParam);
其中 fwButtons 可以为 JOY_BUTTON1、JOY_BUTTON2、JOY_BUTTON3、JOY_BUTTON4 这四个的组合。表示在发出这个消息时这些按键是被按下的。xPos 和 yPos 就是当前的位置。我用的手柄比较初级,位置只能是 0、32767 和 65535,分别对应负位置、零位和正位置。
MM_JOY1BUTTONDOWN 对应有按键按下。
fwButtons = wP
xPos = LOWORD(lParam);
yPos = HIWORD(lParam);
其中 fwButtons 可以为 JOY_BUTTON1CHG 、JOY_BUTTON2CHG、JOY_BUTTON3CHG、JOY_BUTTON4CHG ,也可以是 JOY_BUTTON1、JOY_BUTTON2、JOY_BUTTON3、JOY_BUTTON4。xPos 和 yPos 就是当前的位置。
MM_JOY1BUTTONUP 表示一个按键被释放了。
fwButtons = wP
xPos = LOWORD(lParam);
yPos = HIWORD(lParam);
其中 fwButtons 可以为 JOY_BUTTON1CHG 、JOY_BUTTON2CHG、JOY_BUTTON3CHG、JOY_BUTTON4CHG ,也可以是 JOY_BUTTON1、JOY_BUTTON2、JOY_BUTTON3、JOY_BUTTON4。xPos 和 yPos 就是当前的位置。
知道这些就可以编程控制游戏手柄了。由于按下游戏手柄的其他按键时不会产生消息,所以用起来不是很方便。所以建议不用这种消息机制。而是自己在程序中建立一个独立的线程,这个线程轮询游戏手柄的状态,根据自己的需要,发送各种自定义消息。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1291308次
积分:15825
积分:15825
排名:第470名
原创:336篇
转载:16篇
译文:15篇
评论:552条
文章:20篇
阅读:19459
文章:32篇
阅读:46918
文章:11篇
阅读:42921
文章:22篇
阅读:86928
文章:31篇
阅读:110077
(7)(7)(9)(15)(9)(22)(21)(5)(7)(4)(6)(3)(5)(4)(5)(6)(4)(2)(1)(9)(4)(4)(7)(6)(2)(3)(4)(9)(8)(2)(3)(8)(2)(6)(2)(3)(3)(4)(8)(4)(4)(14)(1)(10)(6)(2)(6)(13)(17)(11)(19)(24)下次自动登录
现在的位置:
& 综合 & 正文
C#对游戏手柄的编程开发-API篇(1)
前段时间花38元从网上买了一对北通的USB游戏手柄,这样周末与晚上的休闲时间就可以玩玩孩儿时的SFC与街机模拟游戏了。
某日在某个网站上玩一个Flash游戏时,突然想到,如果也能使用手柄来玩Flash游戏,那该多爽 。但可惜的是,目前的Flash都是不支持对游戏手柄进行编程,这不免是Flash中的一个遗憾。。
虽然Flash中不支持对游戏手柄进行编程,但我们可以换种方法,做一个辅助(外挂? ),将手柄中的操作事件转换为Flash中可接受的键盘与鼠标操作事件,这样不就可以使用游戏手柄来玩Flash游戏了吗?!于是,上网查了相关资料,但却发现只有C++方面的案例,而C#一个也找不,这不打紧,自己动手,丰衣足食 。
(注:类似这样的功能,网络已有现成的软件,是一个日本人开发的,叫JoyToKey)
对游戏手柄进行操作,大概有两种方式:采用系统API或者使用DirectInput操作游戏手柄设备。(也许还有其它方式,但我的知识范围有限,其它方式就不得而知了)
采用系统API是一种最简单的方式,因为系统已帮我们封装好了所有细节,我们只要在程序中定时取得游戏手柄设备的状态就可以了(轮循)。
操作游戏手柄(杆)的API有以下几个:
joyGetNumDevs
获取当前系统支持的游戏设备数量
joyGetDevCaps
查询获取指定的游戏杆设备以确定其性能
joySetCapture
向系统申请捕获某个游戏设备并定时将该设备的状态值通过消息发送到某个窗口
joyReleaseCapture
释放对某个游戏设备的捕获
获取游戏设备的坐标位置和按钮状态
joyGetPosEx
获取游戏设备的坐标位置和按钮状态
joyGetThreshold
查询指定的游戏杆设备的当前移动阈值
joySetThreshold
设置指定的游戏杆设备的移动阈值
其中,根据调用不同的方法又可分为两种方式。
1)被动方式:
调用joySetCapture方法,向系统申请对某个游戏手柄的捕捉,如果成功申请,系统将会定时将此游戏手柄的状态信息通过消息方式通知到我们的某个窗口上。
2)主动方式:
即是根据我们自己的需要,按需调用joyGetPos或joyGetPosEx方法查询获取某个游戏手柄的当前状态。
而在本篇中,我们要讲解的只是“被动方式”。
joySetCapture方法的C#定义原型如下:
/// &summary&
/// 向系统申请捕获某个游戏杆并定时将该设备的状态值通过消息发送到某个窗口
/// &/summary&
/// &param name="hWnd"&窗口句柄&/param&
/// &param name="uJoyID"&指定游戏杆(0-15),它可以是JOYSTICKID1或JOYSTICKID2&/param&
/// &param name="uPeriod"&每隔给定的轮询间隔就给应用程序发送有关游戏杆的信息。这个参数是以毫妙为单位的轮询频率。&/param&
/// &param name="fChanged"&是否允许程序当操纵杆移动一定的距离后才接受消息&/param&
/// &returns&&/returns&
[DllImport("winmm.dll")]
public static extern int joySetCapture(IntPtr hWnd, int uJoyID, int uPeriod, bool fChanged);
当我们调用此方法向系统申请捕获某个游戏手柄后,如果成功,则返回JOYERR_NOERROR(值为0),否则返回其它值的话表示申请失败。并且在不再需要捕获游戏手柄时要记得调用joyReleaseCapture方法释放捕捉。
如果申请成功,系统将会定时(根据uPeriod的值决定时间的长短)将游戏手柄的状态以消息包形式发送到hWnd对应的窗口界面。所以我们必须要在程序中处理对应的消息(如重写WndProc方法进行处理)。
并且根据不同的uJoyID值,系统发送的消息号又会有所不同,如对于JOYSTICKID1系统将会分别发送以下消息包:
MM_JOY1MOVE
当手柄的位置已变动或按了某些按钮时,将会发送此消息包。
MM_JOY1BUTTONDOWN
当手柄的A,B,C,D四个按钮中的一个或多个正被按下时,将会发送此消息包。
MM_JOY1BUTTONUP
当手柄的A,B,C,D四个按钮中的一个或多个正被弹起时,将会发送此消息包。
而对于JOYSTICKID2 系统发出的消息包分别为MM_JOY2MOVE、MM_JOY2BUTTONDOWN、MM_JOY2BUTTONUP!
并且要注意!不管你有没有按游戏手柄上的按钮,系统也会定时发送MM_JOYXMOVE消息!!
怎样判断按了哪些键?
在消息包中,游戏手柄的状态信息(按钮状态)分别存储在消息包中的WParam与LParam参数。
1)WParam参数:
对于游戏手柄来说WParam存储的是除了上下左右四个方向键之外的所有按钮中当前被按下的按钮值,它的值是一个复合值。如它的值为JOY_BUTTON1 | JOY_BUTTON2时,就表明按下的按键是1号和2号按钮。
注意:对于MM_JOYXBUTTONDOWN与MM_JOYXBUTTONUP两个消息,用于判断的按钮值是不同于MM_JOYXMOVE的按钮值!!
2)LParam参数:
此参数存储的是游戏手柄的坐标参数,并且此参数的高16位存储的是Y坐标值,低16位存储的是X坐标值。
而对于游戏手柄来说,判断上下左右四个方向键有没有被按下就是通过此参数进行判断的。如果当四个方向键都没有被按下时,表示当前游戏手柄处于中心坐标中!也就是X,Y坐标都是在中心点位置上,而当某些方向键被按下时,X,Y坐标将根据所按的键向对应方向偏移。如当按了向右键,则X坐标向右偏移,Y坐标保持在中心点位置,而如果按了右、上两个方向键同时按下,则X坐标向右偏移,Y坐标向上偏移。所以我们可以根据LParam参数取得X,Y坐标的值,然后再根据其中心点来判断。参考如下:
/// &summary&
/// 获取X,Y轴的状态
/// &/summary&
/// &param name="lParam"&&/param&
/// &param name="buttons"&&/param&
private void GetXYButtonsStateFromLParam(int lParam, ref JoystickButtons buttons)
//处理X,Y轴
int x = lParam & <span style="color: #x0000FFFF;
//低16位存储X轴坐标
int y = (int)((lParam & <span style="color: #xFFFF0000) && <span style="color: #); //高16位存储Y轴坐标(不直接移位是为避免0xFFFFFF时的情况)
int m = <span style="color: #x7EFF;
//中心点的值
if (x & m)
buttons |= JoystickButtons.R
else if (x & m)
buttons |= JoystickButtons.L
if (y & m)
buttons |= JoystickButtons.D
else if (y & m)
buttons |= JoystickButtons.UP;
好了,对游戏手柄的“被动方式”编程就讲解完成了,剩下的就是要怎么利用游戏手柄来实现模拟键盘或鼠标的操作了……
PS:如果各位有兴趣的可考虑一下怎么实现游戏手柄的“主动方式”编程开发。
示例代码下载:
&&&&推荐文章:
【上篇】【下篇】joypad 游戏手柄驱动代码,适合于 按键 的开发 用。 Other Games 其他
259万源代码下载-
&文件名称: joypad& & [
& & & & &&]
&&所属分类:
&&开发工具: C-C++
&&文件大小: 1 KB
&&上传时间:
&&下载次数: 13
&&提 供 者:
&详细说明:游戏手柄驱动代码,适合于手柄游戏按键驱动代码的开发和应用。-Game controller driver code, suitable for Game Consoles key driver code development and applications.
文件列表(点击判断是否您需要的文件,如果是垃圾请在下面评价投诉):
&&joypad.c
&[]:和说明完全不符
&近期下载过的用户:
&输入关键字,在本站259万海量源码库中尽情搜索:
&[] - 一个windows下的驱动程序,其实是个简单的内核模块,作用是可以把百通的游戏手柄变成一个鼠标
&[] - 开发单片机的USB,实现游戏手柄的功能,并能够在Windows系统中的游戏控制器可以查看到。
&[] - 手柄驱动DEMO程序源码,一般游戏手柄和专业手柄均使用
&[] - 游戏手柄的接口程序,通过directX获取手柄的按键变化。
&[] - 基于windows CE 平台的游戏手柄驱动,支持通用USB手柄,给予HID类,把手柄映射成为键盘,可以通过调整映射表的SC和VK映射不同的按键键值。
&[] - 这个是虚拟手柄的驱动。分别是DDK版本和DriverStudio版本。完全可以实现市面上的虚拟手柄,发挥DIY精神。
&[] - 用ANDROID手机模拟方向盘操纵杆,键盘模式将重力感应器信号提取并翻译成键盘控制信号,方向盘模式将重力感应器信号翻译成方向盘扭动角度电脑如何用手柄玩游戏
您好,我的笔记本是win7系统,我想知道应该怎样设置,才能用手柄玩游戏
已有1个回答
内容为广告/垃圾,我要举报!
特聘专家具有协助内容审核的特权
举报后内容将不能在前台展示
错乱举报会导致该权利被剥夺
选择举报原因×
擅长领域:
& 对于广大电脑游戏爱好者来说,一个反应灵敏的手柄是必备外设之一。下面就给大家介绍如何在win7系统的电脑上设置和调试游戏手柄。一:如何查找手柄1.将游戏手柄USB端口插在电脑上后,电脑会提示接入了新的USB设备。待提示消失后,我们点击【开始】菜单,选择【设备和打印机】。2.打开【设备和打印机】后,可以看到电脑上已连接的所有设备。在【设备】栏里可以找到一个游戏控制器的图标,这就是我们刚才连接上的手柄了。二:如何测试游戏手柄功能1.用鼠标选中游戏控制器图标,按鼠标右键,选择右键菜单中的【游戏控制器设置】功能。2.在【游戏控制器】设置界面点击右下角的【属性】按钮。3.在【测试】选项卡下我们可以测试手柄各按钮是否正常工作。首先,可以旋转和按下手柄中的左面方向舵和方向按键,观看“X轴/Y轴”上方的十字光标运动是否正常。最终十字光标应居中显示。4.然后我们可以测试手柄中的右方向舵是否工作正常。测试过程中,按钮触发的功能对应下图中的圆点会呈红色闪烁状态。测试其他按钮时也类似,不再赘述。三:校准游戏手柄1.如果在上面的测试环节发现游戏手柄工作不正常,可以选择【设置】选项卡中的【校准】按钮功能来校准游戏手柄。2.进入“设备校准向导”后根据提示依次点击【下一步】。3.在【校准轴】界面,将手柄左方向舵旋转几圈,重新定位中心点。这个过程校准的是游戏手柄的“X轴/Y轴”。4.下面进入Z轴校准程序。首先,上下移动Z轴,也就是移动手柄上的右方向舵来校准。5.然后,将Z轴进行旋转校准。6.Z轴校准完毕后会自动跳转到下述界面,点击【完成】按钮后就可以正常使用手柄了。
留下你的评论
为什么我都跟着步骤走了,打开游戏还是不能用手柄控制啊,我玩的的是火影究极风暴
微信公众账号ZOL问答堂
关注微信,随时随地解答您的疑惑
ZOL问答堂官方微博@ZOL问答堂
关注成功!该问题被回答后,将给您发送站内短信。
您也可以通过关注问答堂微信,及时获得您关注问题的回答。
微信关注问题方法“”}

我要回帖

更多关于 游戏程序开发培训机构 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信