《专题6键盘和鼠标控制课件》由会员分享,可在线阅读,更多相关《专题6键盘和鼠标控制课件(43页珍藏版)》请在金锄头文库上搜索。
1、Copyright 2008 By Neusoft Group. All rights reserved专题6 键盘和鼠标控制专题6键盘和鼠标控制课件抛砖引玉抛砖引玉交互性是游戏的最基本特征,玩家必须与计算机不断地交交互性是游戏的最基本特征,玩家必须与计算机不断地交互并得到反应,这才是完整的游戏体验。那么,玩家和游互并得到反应,这才是完整的游戏体验。那么,玩家和游戏如何进行交互?戏如何进行交互?目前很流行的游戏控制方式:目前很流行的游戏控制方式:w键前进,键前进,a键向左移动,键向左移动,s键后退,键后退,d键向右移动,按下鼠标左键攻击,按住鼠标右键向右移动,按下鼠标左键攻击,按住鼠标右键转动
2、视角键转动视角游戏控制是一款游戏的基本要素,没有对游戏的控制,玩游戏控制是一款游戏的基本要素,没有对游戏的控制,玩家和游戏就无从交互。家和游戏就无从交互。Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件麻雀虽小,五脏俱全麻雀虽小,五脏俱全传统游戏控制传统游戏控制DirectInput 简介简介DirectX键盘控制键盘控制DirectX鼠标控制鼠标控制游戏控制综合运用游戏控制综合运用 Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件在在
3、Win32 API编程中,编程中,键盘和鼠标的用户输键盘和鼠标的用户输入信息并不是直接传入信息并不是直接传递给应用程序来处理递给应用程序来处理的,而是转发回的,而是转发回Windows操作系统,操作系统,最后由最后由Windows回调回调应用程序的窗口过程应用程序的窗口过程函数进行相应的消息函数进行相应的消息代码处理。这种处理代码处理。这种处理用户输入的方式,执用户输入的方式,执行效率低。行效率低。Copyright 2008 By Neusoft Group. All rights reserved传统游戏控制传统游戏控制case WM_KEYDOWN: switch (wParam) ca
4、se VK_LEFT: / 处理左箭头光标移动键的按键消息 break; case VK_RIGHT: / 处理右箭头光标移动键的按键消息 break; return 0;专题6键盘和鼠标控制课件DirectInput是是DirectX的一个组件接口,提供了的一个组件接口,提供了大量的接口函数处理用户在键盘、鼠标、游戏杆大量的接口函数处理用户在键盘、鼠标、游戏杆以及力反馈等游戏装置上的输入。以及力反馈等游戏装置上的输入。DirectInput直接与硬件驱动程序通信,因此它可直接与硬件驱动程序通信,因此它可以较快的处理用户的输入。并且在控制面板上做以较快的处理用户的输入。并且在控制面板上做的任何
5、键盘和鼠标的属性设置(如键盘按键的延的任何键盘和鼠标的属性设置(如键盘按键的延迟重复率和鼠标的左右手习惯等),都不会对应迟重复率和鼠标的左右手习惯等),都不会对应用用DirectInput的程序起作用,除非是修改由驱动的程序起作用,除非是修改由驱动程序提供的属性设置。程序提供的属性设置。Copyright 2008 By Neusoft Group. All rights reservedDirectInput 简介简介专题6键盘和鼠标控制课件DirectX键盘控制键盘控制创建创建IDirectInput接口对象接口对象创建创建DirectInput设备对象设备对象设置设置DirectInpu
6、t设备的数据格式设备的数据格式设置设置DirectInput设备的协调级别设备的协调级别设置设置DirectInput设备的属性设备的属性获取输入设备的访问权获取输入设备的访问权读取键盘的输入读取键盘的输入关闭关闭DirectInput,释放输入设备,释放输入设备专题6键盘和鼠标控制课件1、创建、创建IDirectInput接口对象接口对象在创建具体的输入设备对象之前,首先要利用在创建具体的输入设备对象之前,首先要利用DirectInput8Create建立一个建立一个IDirectInput接口对象。接口对象。 HRESULT DirectInput8Create( HINSTANCE hi
7、nst, /当前创建当前创建IDirectInput对象的应用程序句柄对象的应用程序句柄 DWORD dwVersion, / DirectInput版本号,通常取值版本号,通常取值DIRECTINPUT_VERSION, 在当前的在当前的dinput.h头文件中,头文件中, DIRECTINPUT_VERSION定义为定义为0x0800 REFIID riidltf, /指明所需创建的指明所需创建的IDirectInput对象的唯一标志符,对象的唯一标志符, 一般取值为一般取值为IID_IDirectInput8 LPVOID * ppvOut, /存放存放IDirectInput接口对象指
8、针地址接口对象指针地址 LPUNKNOWN punkOuter /一般取值为一般取值为NULL); Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件例:例: DirectInput对象的创建步骤对象的创建步骤 IDirectInput8* Input=0; HRESULT hr=0; hr = DirectInput8Create( hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (void*)&Input, NULL); if(FAILED(hr):Messa
9、geBox(0, DirectInput8Create( ) - FAILED, 0, 0);return false;Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件2、创建、创建DirectInput设备对象设备对象建立建立DirectInput接口对象之后,就可以利用接口对象之后,就可以利用IDirectInput8接口所提供的接口所提供的CreateDevice函数,为键盘、函数,为键盘、鼠标和游戏杆等输入装置建立一个对应的鼠标和游戏杆等输入装置建立一个对应的DirectInput设备设备对象,此后就可用设
10、备对象来读取用户的输入。对象,此后就可用设备对象来读取用户的输入。 HRESULT CreateDevice( REFGUID rguid, /所要创建的输入设备的标志符,键盘取值为所要创建的输入设备的标志符,键盘取值为 GUID_SysKeyboard,鼠标取值为,鼠标取值为GUID_SysMouse LPDIRECTINPUTDEVICE * lplpDirectInputDevice, /创建的输入设备对象的指针的地址创建的输入设备对象的指针的地址 LPUNKNOWN pUnkOuter /一般取值为一般取值为NULL );Copyright 2008 By Neusoft Group.
11、 All rights reserved专题6键盘和鼠标控制课件例:创建例:创建DirectInput键盘设备键盘设备 IDirectInputDevice8* InputDevice=0; hr=Input-CreateDevice(GUID_SysKeyboard, &InputDevice, NULL); if(FAILED(hr) :MessageBox(0, CreateDevice()- Keyboard - FAILED, 0, 0); d3d:Release(Input); /释放接口释放接口 return false; 例:创建例:创建DirectInput鼠标设备鼠标设备
12、IDirectInputDevice8* InputDevice=0; hr=Input-CreateDevice(GUID_SysMouse, &InputDevice, NULL); if(FAILED(hr) :MessageBox(0, CreateDevice ( )-Mouse-FAILED, 0, 0); d3d:Release(Input); /释放接口释放接口 return false; Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件3、设置、设置DirectInput设备的数据格式设备的数据格
13、式每种设备都有一种用于读取数据的特定数据格式,因此要每种设备都有一种用于读取数据的特定数据格式,因此要使程序从设备读取数据,首先必须告诉使程序从设备读取数据,首先必须告诉 DirectInput读取这读取这种数据所采用的格式。可以用种数据所采用的格式。可以用IDirectInputDevice8接口提接口提供的供的SetDataFormat函数实现。函数实现。 HRESULT SetDataFormat( LPCDIDATAFORMAT lpdf ); lpdf 指向指向DIDATAFORMAT结构体,该结构体用来填写结构体,该结构体用来填写DirectInput设备的属性值。可以用该结构体预
14、先定义出来的全局变量:设备的属性值。可以用该结构体预先定义出来的全局变量:c_dfDIKeyboard 、c_dfDIMouse 、c_dfDIMouse2、c_dfDIJoystick 和和c_dfDIJoystick2 来说明键盘、鼠标和游戏杆设备来说明键盘、鼠标和游戏杆设备的数据格式。的数据格式。Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件例:设置键盘设备的数据格式例:设置键盘设备的数据格式 hr=InputDevice-SetDataFormat(&c_dfDIKeyboard); if(FAILED(
15、hr) :MessageBox(0, SetDataFormat( ) - FAILED, 0, 0); d3d:Release(InputDevice); /释放接口释放接口 d3d:Release(Input); /释放接口释放接口 return false; Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件4、设置、设置DirectInput设备的协调级别设备的协调级别如果同一个物理输入设备建立了多个如果同一个物理输入设备建立了多个DirectInput设备实例,设备实例,必须处理这些实例相互间的协调级别。此
16、外,还需要设定必须处理这些实例相互间的协调级别。此外,还需要设定设备实例与系统的其他对象的协调级别。这个协调级别是设备实例与系统的其他对象的协调级别。这个协调级别是通过通过IDirectInputDevice8接口的接口的 SetCooperativeLevel函数实现。函数实现。 HRESULT SetCooperativeLevel ( HWND hwnd, /设备所属的窗口句柄设备所属的窗口句柄 DWORD dwFlags /协调级别标识协调级别标识 );Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件协调级
17、别标识协调级别标识dwFlags:DISCL_BACKGROUND:即即使使所所属属的的窗窗口口不不是是活活动动窗窗口口,仍然可取得输入设备的数据仍然可取得输入设备的数据DISCL_EXCLUSIVE :独独占占输输入入设设备备,不不过过如如果果其其他他设设备备采采用用非非独独占占方方式式使使用用这这个个已已被被独独占占的的输输入入设设备备,那那么么还还是允许的是允许的DISCL_FOREGROUND:输输入入设设备备的的输输入入数数据据只只有有在在所所属窗口处于活动状态时才可读取属窗口处于活动状态时才可读取DISCL_NONEXCLUSIVE :非非独独占占输输入入设设备备,其其他他 Dir
18、ectInput设备实例可共享该输入设备的读取权设备实例可共享该输入设备的读取权DISCL_NOWINKEY:使使Windows的的注注销销键键失失效效,阻阻止止用户中断应用程序的运行用户中断应用程序的运行 注意:协调级别标识注意:协调级别标识 DISCL_BACKGROUND 和和DISCL_EXCLUSIVE不能同时不能同时使用,否则,将导致设备的协调级别设置失败。使用,否则,将导致设备的协调级别设置失败。Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件例例 : 将将 DirectInput设设 备备 的的 协
19、协 调调 级级 别别 设设 置置 为为DISCL_FOREGROUND和和DISCL_EXCLUSIVE。 hr=InputDevice-SetCooperativeLevel( hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE ); if(FAILED(hr) :MessageBox(0, SetCooperativeLevel( )-FAILED, 0, 0); d3d:Release(InputDevice); /释放接口释放接口 d3d:Release(Input); /释放接口释放接口 return false; Copyright 2008 By N
20、eusoft Group. All rights reserved专题6键盘和鼠标控制课件5、设置、设置DirectInput设备的属性设备的属性前面介绍了用前面介绍了用DirectX SDK预定义的全局变量:预定义的全局变量:c_dfDIKeyboard 、c_dfDIMouse 、c_dfDIMouse2、c_dfDIJoystick 和和c_dfDIJoystick2 来设置来设置DirectInput设备设备(键盘、键盘、鼠标和游戏杆鼠标和游戏杆)的数据格式,这种做法相当于设置的数据格式,这种做法相当于设置了了DirectInput设备的一些默认属性。设备的一些默认属性。下面介绍默认状
21、态下的两个属性。下面介绍默认状态下的两个属性。Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件 属性属性1:l在默认的情形下,在默认的情形下,DirectInput设备以立即模式(如果按键设备以立即模式(如果按键速度非常快,那么在速度非常快,那么在DirectInput读取数据那一刻之前的按读取数据那一刻之前的按键数据将不能被键数据将不能被DirectInput设备读取)获取输入信息,与设备读取)获取输入信息,与立即模式相对应的是缓冲模式,此时设备输入数据将被放立即模式相对应的是缓冲模式,此时设备输入数据将被放进缓
22、冲区中供进缓冲区中供DirectInput设备使用。设备使用。l 对于游戏开发来说,通常依照对于游戏开发来说,通常依照键盘和游戏杆键盘和游戏杆的各种按键执的各种按键执行画面的更新,因此,多用行画面的更新,因此,多用DirectInput的的立即模式立即模式来读取来读取它们的输入数据。相反的,在一个画面中它们的输入数据。相反的,在一个画面中鼠标鼠标的移动是连的移动是连贯的,为了使游戏程序可处理多次连续的鼠标移动量,就贯的,为了使游戏程序可处理多次连续的鼠标移动量,就需要采用需要采用DirectInput的的缓冲模式缓冲模式来读取鼠标的输入。来读取鼠标的输入。Copyright 2008 By N
23、eusoft Group. All rights reserved专题6键盘和鼠标控制课件 属性属性2:以以相对移动模式相对移动模式来获取鼠标的来获取鼠标的X-Y轴移动量。轴移动量。如下图所示:鼠标从点如下图所示:鼠标从点(7,8)-(20,30)-(50,40)- (70,90)进进行移动。行移动。(7,8)(50,40)(20,30)(70,90)第一次移动量(第一次移动量(20-7,30-8)=(13,22)第二次移动量(第二次移动量(50-20,40-30)=(30,10)第三次移动量(第三次移动量(70-50,90-40)=(20,50)DirectInput设备默认获取鼠标相对于上
24、一次位置的设备默认获取鼠标相对于上一次位置的X和和Y轴轴的增量,负数表示反方向移动。的增量,负数表示反方向移动。可以设置鼠标的移动模式为绝对移动模式。可以设置鼠标的移动模式为绝对移动模式。Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件修改修改DirectInput设备的属性,可使用设备的属性,可使用IDirectInputDevice8接口的接口的SetProperty函数来实现。该函数必须在函数来实现。该函数必须在Acquire获获取取DirectInput设备的使用权之前调用,否则函数调用失败。设备的使用权之
25、前调用,否则函数调用失败。HRESULT SetProperty( REFGUID rguidProp, /属性标志(全局统一标志符)属性标志(全局统一标志符) LPCDIPROPHEADER pdiph /设置具体的属性值设置具体的属性值 ); rguidProp 一个全局统一标志符,用于指定需要设置的属性。一个全局统一标志符,用于指定需要设置的属性。 DIPROP_BUFFERSIZE:设置设置DirectInput缓冲区的大小。缓冲区的大小。 DIPROP_AXISMODE:设置设置DirectInput读取鼠标读取鼠标X-Y轴移动轴移动 量的模式。量的模式。 DIPROP_DEADZO
26、NE:设置游戏杆的死区。设置游戏杆的死区。 pdiph 一个指向一个指向DIPROPHEADER结构体的指针,设置具体的属性值。结构体的指针,设置具体的属性值。Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件typedef struct DIPROPHEADER DWORD dwSize; /包含头部的整个结构体的大小,一般为包含头部的整个结构体的大小,一般为 sizeof(DIPROPDWORD) DWORD dwHeaderSize; / 结构体头部的大小,一般为结构体头部的大小,一般为 sizeof(DIPR
27、OPHEADER ) DWORD dwObj; / 属性对象,由属性对象,由dwHow参数决定参数决定 DWORD dwHow; /说明说明dwObj参数应如何交互参数应如何交互 DIPROPHEADER, *LPDIPROPHEADER; typedef struct DIPROPDWORD DIPROPHEADER diph; / DIPROPHEADER结构体结构体 DWORD dwData; /缓冲区数组元素个数缓冲区数组元素个数 DIPROPDWORD, *LPDIPROPDWORD; DIPROPHEADER diphDWORD dwDataDIPROPDWORDCopyright
28、 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件例:例:DirectInput鼠标设备使用缓冲区读取鼠标设备使用缓冲区读取数据的属性设置。数据的属性设置。 DIPROPDWORD dipROPWORD; dipROPWORD.diph.dwSize = sizeof(DIPROPDWORD ); dipROPWORD.diph. dwHeaderSize = sizeof(DIPROPHEADER ); dipROPWORD.diph. dwObj = 0; dipROPWORD.diph. dwHow = DIPH_DEVICE;
29、 dipROPWORD. dwData = 10; /缓冲区的数组元素个数缓冲区的数组元素个数 if(FAILED(InputDevice-SetProperty( DIPROP_BUFFERSIZE, & dipROPWORD.diph) :MessageBox(0, SetProperty( )-FAILED, 0, 0); return false; Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件6、获取输入设备的访问权、获取输入设备的访问权获取了输入设备的访问权,才可读取用户输入的数据。这获取了输入设备的
30、访问权,才可读取用户输入的数据。这个访问权是通过个访问权是通过IDirectInputDevice8接口的接口的Acquire函数函数实现。实现。例例:获取设备的访问权。获取设备的访问权。 hr=InputDevice-Acquire(); if(FAILED(hr) :MessageBox(0, Acquire( )-FAILED, 0, 0); d3d:Release(InputDevice); d3d:Release(Input); /释放接口释放接口 return false; HRESULT Acquire(VOID); Copyright 2008 By Neusoft Group
31、. All rights reserved专题6键盘和鼠标控制课件7 、读取键盘的输入、读取键盘的输入当创建了当创建了DirectInput设备,设置它的数据格式和协调级别,设备,设置它的数据格式和协调级别,并获取了访问权之后,就可以开始读取键盘的输入。并获取了访问权之后,就可以开始读取键盘的输入。要存储键盘数据,必须使用一个大小为要存储键盘数据,必须使用一个大小为256字节的数组,字节的数组,每个字节存储一个键的状态,这样就给出了保存每个字节存储一个键的状态,这样就给出了保存256个键个键的空间。每个字节存储键当前的状态信息,即键是否被按的空间。每个字节存储键当前的状态信息,即键是否被按下。
32、要得到键的状态,就要检查高位(字节),如果置位,下。要得到键的状态,就要检查高位(字节),如果置位,键就被按下;如果为零,键就未被按下。在键就被按下;如果为零,键就未被按下。在DirectInput 中,每个键都有一个属于自己的宏,这些宏都以中,每个键都有一个属于自己的宏,这些宏都以DIK_为前为前缀。缀。A键定义为键定义为DIK_A,ESC为为DIK_ESCAPE等等。Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件首先建立首先建立1个个256B的缓冲区以接收键盘的输入数据,然后的缓冲区以接收键盘的输入数据,然后
33、不断调用不断调用IDirectInputDevice8:GetDeviceState函数将函数将键盘输入数据读入建立的缓冲区中。键盘输入数据读入建立的缓冲区中。 GetDeviceState执行成功将返回执行成功将返回DI_OK,否则返回否则返回DIERR_INPUTLOST和和DIERR_NOTACQUIRED等错误码。等错误码。 DIERR_INPUTLOST的错误码表明的错误码表明DirectInput设备已丢失,这种情况通常发生在窗口程序失去焦点,共享的设备已丢失,这种情况通常发生在窗口程序失去焦点,共享的键盘硬件已被其他应用程序获得控制权,此时需要利用键盘硬件已被其他应用程序获得控制
34、权,此时需要利用Acquire函数使当前函数使当前应用程序重获它的访问控制权。应用程序重获它的访问控制权。HRESULT GetDeviceState( DWORD cbData, /该缓冲区的字节大小该缓冲区的字节大小(一般取为一般取为256B) LPVOID lpvData /缓冲区的指针缓冲区的指针 );Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件例:例: char keyBuffer256;HRESULT hr;hr=InputDevice-GetDeviceState(sizeof(keyBuffer
35、), (LPVOID)keyBuffer);if(hr=DIERR_INPUTLOST) InputDevice-Acquire(); /重新获取键盘的使用权重新获取键盘的使用权hr=InputDevice-GetDeviceState(sizeof(keyBuffer), (LPVOID)keyBuffer);if(FAILED(hr) :MessageBox(0, DIERR_NOTACQUIRED , 0, 0);return false;Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件当用户按键被读入键盘缓
36、冲区当用户按键被读入键盘缓冲区keyBuffer后,就可后,就可以判断出具体是哪个按键被按下。如下给出了以判断出具体是哪个按键被按下。如下给出了“”和和“”键被按下的判断。键被按下的判断。if(keyBufferDIK_RIGHT & 0x80)MessageBox(NULL,RIGHT_KEY_PRESSED,提示提示,0);if(keyBufferDIK_LEFT & 0x80) MessageBox(NULL ,LEFT_KEY_PRESSED ,提示提示,0);if(keyBufferDIK_A & 0x80)&(keyBufferDIK_LCONTROL & 0x80) Messag
37、eBox(NULL ,Ctrl+A_PRESSED ,提示提示,0);Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件每次用户按键,都会依照按键的每次用户按键,都会依照按键的DIK索引号在索引号在keyBuffer相相应的字节上(应的字节上(8bit)存放该键的状态信息,实际是在缓冲)存放该键的状态信息,实际是在缓冲区的相应字节处更新该按键的状态信息。区的相应字节处更新该按键的状态信息。例如,例如,“ESC”键的键的DIK索引号为索引号为1,如果该键被按下,然,如果该键被按下,然后被后被DirectInput设备读
38、取后,它的状态信息被放在设备读取后,它的状态信息被放在keyBuffer数组的第一个字节处。以此类推数组的第一个字节处。以此类推,由于我们,由于我们的键盘的键的个数不会超过的键盘的键的个数不会超过256,因此,一般设置键盘缓冲,因此,一般设置键盘缓冲区的数组大小为区的数组大小为256。还有一点,由于键盘上是采用立即模式来读取数据,在还有一点,由于键盘上是采用立即模式来读取数据,在keyBuffer缓冲区中保存的是键盘所有键的状态,并没有对缓冲区中保存的是键盘所有键的状态,并没有对同一个键的多次按下进行缓存。但是可以对同时按下多个同一个键的多次按下进行缓存。但是可以对同时按下多个键进行判断。键进
39、行判断。Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件SDK中的Keyboard Device 枚举了所有键盘按键的DIK码。Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件8、关闭、关闭DirectInput,释放输入设备,释放输入设备DirectInput对象在不再被使用的时候,需对象在不再被使用的时候,需要释放对象,如:要释放对象,如:if(pIDirectInputDevice) pIDirectInputDevice-Una
40、cquire(); /释放 DirectInput设备的使用权 SafeRelease(pIDirectInputDevice);/释放 DirectInput设备对象 SafeRelease(pIDirectInput); /释放DirectInput对象专题6键盘和鼠标控制课件DirectX鼠标控制鼠标控制创建创建IDirectInput接口对象接口对象创建创建DirectInput设备对象设备对象设置设置DirectInput设备的数据格式设备的数据格式设置设置DirectInput设备的协调级别设备的协调级别设置设置DirectInput设备的属性设备的属性获取输入设备的访问权获取输入
41、设备的访问权读取鼠标的输入读取鼠标的输入关闭关闭DirectInput,释放输入设备,释放输入设备专题6键盘和鼠标控制课件可采用可采用DirectInput立即模式和缓冲模式来读取鼠立即模式和缓冲模式来读取鼠标的按键输入,不过由于鼠标输入的连续性及游标的按键输入,不过由于鼠标输入的连续性及游戏程序往往需要在一个动画帧中处理多次的鼠标戏程序往往需要在一个动画帧中处理多次的鼠标输入,因此,我们将基于缓冲模式来介绍鼠标的输入,因此,我们将基于缓冲模式来介绍鼠标的输入读取。输入读取。在建立了在建立了DirectInput鼠标设备,设置了它的数据鼠标设备,设置了它的数据格式和协调级别后,就必须使用格式和
42、协调级别后,就必须使用SetProperty函数函数设置设置DirectInput设备缓冲区的属性。(见设备缓冲区的属性。(见5)下面就是鼠标数据的读取方法。下面就是鼠标数据的读取方法。读取鼠标的输入读取鼠标的输入Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件首先,声明一个首先,声明一个DIDEVICEOBJECTDATA类型的数组类型的数组diDeviceObjectData。鼠标的各种按键数据(如单击左。鼠标的各种按键数据(如单击左键、单击右键、鼠标的键、单击右键、鼠标的X轴移动和轴移动和Y轴移动量等)将依次
43、轴移动量等)将依次放在这个数组中,因此,这个数组真正起到了缓冲区的作放在这个数组中,因此,这个数组真正起到了缓冲区的作用。这个数组的长度必须与用。这个数组的长度必须与SetProperty所设置的缓冲区所设置的缓冲区的数组元素的个数相同。的数组元素的个数相同。typedef struct DIDEVICEOBJECTDATA DWORD dwOfs; /见下页见下页 DWORD dwData; /从设备得到的或者发送给设备的数据从设备得到的或者发送给设备的数据 DWORD dwTimeStamp; /毫秒级的输入事件发生的时间戳毫秒级的输入事件发生的时间戳 DWORD dwSequence;
44、/输入事件的序列号输入事件的序列号 UINT_PTR uAppData; /应用程序定义的动作值,我们没用,忽略应用程序定义的动作值,我们没用,忽略 DIDEVICEOBJECTDATA, *LPDIDEVICEOBJECTDATA; #define ITEMS_NUM 10 /缓冲区的数组元素个数缓冲区的数组元素个数 DIDEVICEOBJECTDATA diDeviceObjectDataITEMS_NUM;Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件typedef enum Mouse_Device DI
45、MOFS_BUTTON0, /鼠标左键的按键状态鼠标左键的按键状态 DIMOFS_BUTTON1, /鼠标右键的按键状态鼠标右键的按键状态 DIMOFS_BUTTON2, /鼠标中间滑轮的按键状态鼠标中间滑轮的按键状态 DIMOFS_BUTTON3, DIMOFS_BUTTON4, DIMOFS_BUTTON5, DIMOFS_BUTTON6, DIMOFS_BUTTON7, DIMOFS_X, /鼠标鼠标X轴的移动量轴的移动量 DIMOFS_Y, /鼠标鼠标Y轴的移动量轴的移动量 DIMOFS_Z, /鼠标滑轮的移动量鼠标滑轮的移动量 Mouse Device, *LPMouse Devic
46、e; 对于鼠标来说,对于鼠标来说,dwOfs参数可取如下枚举的几个参数可取如下枚举的几个DIMOFS_*的鼠标状态值。的鼠标状态值。Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件当当DIDEVICEOBJECTDATA结构体的结构体的dwOfs分量表明当分量表明当前数据为鼠标的按键状态,就可进一步利用结构体的前数据为鼠标的按键状态,就可进一步利用结构体的dwData分量与分量与0x80进行进行“&”与操作,值为与操作,值为1表示这个鼠表示这个鼠标键已按下,否则表示鼠标按键已释放;当标键已按下,否则表示鼠标按键已释
47、放;当DIDEVICEOBJECTDATA结构体的结构体的dwOfs分量表明当前分量表明当前数据为鼠标的轴向移动量,数据为鼠标的轴向移动量, dwData 中的值则是移动量的中的值则是移动量的值。值。/判断鼠标左键按下判断鼠标左键按下if(diDeviceObjectDatai.dwOfs=DIMOFS_BUTTON0) & (diDeviceObjectDatai.dwData & 0x80) return true; /判断鼠标右键按下判断鼠标右键按下if(diDeviceObjectDatai.dwOfs=DIMOFS_BUTTON1) & (diDeviceObjectDatai.dw
48、Data & 0x80) return true; Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件/判断鼠标滚轮按下判断鼠标滚轮按下if(diDeviceObjectDatai.dwOfs=DIMOFS_BUTTON2) & (diDeviceObjectDatai.dwData & 0x80) return true; /累计鼠标的轴向移动量累计鼠标的轴向移动量if(diDeviceObjectDatai.dwOfs=DIMOFS_X) g_lMouseMoveX+=diDeviceObjectDatai.dw
49、Data;if(diDeviceObjectDatai.dwOfs=DIMOFS_Y) g_lMouseMoveY+=diDeviceObjectDatai.dwData; Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件缓冲模式下的程序在读取设备输入时不再使用IDirectInputDevice8: GetDeviceState函数,函数,而是使用而是使用IDirectInputDevice8:GetDeviceData函数,它的原型为:函数,它的原型为:HRESULT GetDeviceData( DWORD
50、cbObjectData, / DIDEVICEOBJECTDATA结构体的字节大小结构体的字节大小 LPDIDEVICEOBJECTDATA rgdod, /存放数据的存放数据的DIDEVICEOBJECTDATA数组(单个元素)地址数组(单个元素)地址 LPDWORD pdwInOut, /一次读入的输入事件数目,通常设置为一次读入的输入事件数目,通常设置为1 DWORD dwFlags /一般为一般为0,表示数据读取后,从缓冲区中删,表示数据读取后,从缓冲区中删除除); Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠
51、标控制课件例:读取鼠标缓冲区数据,通过例:读取鼠标缓冲区数据,通过for循环不断的从驱动程序的缓循环不断的从驱动程序的缓冲区中读取数据到可供冲区中读取数据到可供DirectInput使用的使用的DIDEVICEOBJECTDATA数组缓冲区中。数组缓冲区中。/每次读数据前,一定要使鼠标缓冲区清零,否则读取的数据可能不正确每次读数据前,一定要使鼠标缓冲区清零,否则读取的数据可能不正确ZeroMemory(diDeviceObjectData,sizeof(DIDEVICEOBJECTDATA)*ITEMS_NUM);/循环读取鼠标数据循环读取鼠标数据for(i=0;iGetDeviceData(
52、sizeof(DIDEVICEOBJECTDATA), &diDeviceObjectDatai,&dwReadNum,0);if(hr=DIERR_INPUTLOST)InputDevice-Acquire();hr=InputDevice-GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &diDeviceObjectDatai,&dwReadNum,0);if(FAILED(hr) :MessageBox(0, “GetDeviceData()-FAILED , 0, 0);return false;Copyright 2008 By Neusoft G
53、roup. All rights reserved专题6键盘和鼠标控制课件鼠标的多次输入被读入到一个鼠标的多次输入被读入到一个DIDEVICEOBJECTDATA数组缓数组缓冲区后,需要通过冲区后,需要通过DIDEVICEOBJECTDATA结构体的结构体的dwofs分分量判断鼠标的输入类型,以便进一步的数据处理。例如,上面代量判断鼠标的输入类型,以便进一步的数据处理。例如,上面代码底部的两个码底部的两个if语句,就是判断是否为鼠标的语句,就是判断是否为鼠标的X和和Y轴的移动数据,轴的移动数据,然后分别进行累加以获得总的鼠标然后分别进行累加以获得总的鼠标X-Y轴移动量。轴移动量。if(diDe
54、viceObjectDatai.dwOfs=DIMOFS_X) g_lMouseMoveX+=diDeviceObjectDatai.dwData;if(diDeviceObjectDatai.dwOfs=DIMOFS_Y) g_lMouseMoveY+=diDeviceObjectDatai.dwData; Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件游戏控制综合运用游戏控制综合运用游戏角色控制游戏角色控制 在游戏中,角色的控制一般有三种方式:键盘在游戏中,角色的控制一般有三种方式:键盘控制、鼠标控制、键盘与
55、鼠标同时控制。控制、鼠标控制、键盘与鼠标同时控制。l摄像机控制摄像机控制 在在3D游戏中,最常见的一种方式就是用键盘控游戏中,最常见的一种方式就是用键盘控制角色移动,用鼠标控制摄像机的视角变换。制角色移动,用鼠标控制摄像机的视角变换。专题6键盘和鼠标控制课件常见问题常见问题使用使用DirectInput需要包含需要包含dinput.h头文件,头文件,另外,还需要添加以下库文件:另外,还需要添加以下库文件: dxguid.lib:提供了创建:提供了创建DirectInput设备所需的设备所需的 全局统一标志符。全局统一标志符。 dinput8.lib:提供了:提供了DirectInput接口函数
56、的调接口函数的调 用说明。用说明。Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件学以致用学以致用使用使用DirectInput,通过键盘控制角色的移,通过键盘控制角色的移动,通过鼠标控制摄像机的转动。动,通过鼠标控制摄像机的转动。Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件它山之石它山之石网络游戏客户端编程第网络游戏客户端编程第8章章Visual C+/DirectX9 3D游戏开发导引游戏开发导引 第第5章章Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件锦上添花锦上添花对键盘、鼠标的输入控制进行封装。在以对键盘、鼠标的输入控制进行封装。在以后的程序中可以直接使用这个类,来处理后的程序中可以直接使用这个类,来处理用户的输入。用户的输入。Copyright 2008 By Neusoft Group. All rights reserved专题6键盘和鼠标控制课件