DirectX11 输入设备——DirectInput检测鼠标、键盘状态
1. 什么是DirectInput?
由于windows应用程序的消息机制,Windows 成为了在应用程序和硬件之间的一堵无形的墙。 消息队列记录着各种事件,比如鼠标移动,键盘输入,或来自于操作系统本身的事件。这种获取事件的方式对于 Windows 应用程序效率足够了,但是对于游戏来说却不够快。也有的开发者转向使用另一个 Windows 函数,GetAsyncKeyState,来取得他们所需的信息,这也是可以的。
另一种屏蔽技巧性的方法或设备的巧妙使用的快速取得用户输入的方法,是使用 DirectX SDK 提供的 DirectInput组件,它提供了公共层来解决上述问题。这节课我们就学习使用DirectInput。DirectInput对象用来提供接口来访问DirectInput设备,你所创建的 DirectInput 设备能够使你访问指定的输入设备,比如键盘,操纵杆, 或其它游戏输入设备。
2. 如何创建DirectInput对象?
注意到,使用 DirectInput 的第一步就是创建 DirectInput 对象,函数 DirectInput8Create 就用于此目的,其原型如下:
HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter );
- hInst——用于创建 DirectInput 对象的应用程序实例句柄
- dwVersion——应用程序所要求的 DirectInput 的版本号,用于该参数的标准值是 DIRECTINPUT_VERSION
- riidltf——接口要求标识,可以使用默认值 IID_IDirectInput8 用于该参数
- ppvOut——持有创建成功后的 DirectInput 对象的指针
- punkOuter——该参数一般设为 NULL
下面是一个代码片段,用来创建一个 DirectInput 对象:
HRESULT hr = DirectInput8Create( hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, ( void** )&directInputObject, 0 ); if FAILED( hr ) { return false; }
2. 如何创建DirectInput设备?
现在,你拥有一个有效的 DirectInput 对象,就可以自由创建设备,可以通过使用 CreateDevice 函数完成:
HRESULT CreateDevice( REFGUID rguid, LPDIRECTINPUTDEVICE *lplpDirectInputDevice, LPUNKNOWN pUnkOuter );
- rguid,使用GUID_SysKeyboard 或 GUID_SysMouse 来标识使用键盘或鼠标设备。
- lplpDirectInputDevice,保存创建成功的 DirectInput 设备对象地址。
- 最后一个参数用于处理 COM 接口。大部分应用程序将最后一个参数设置为 NULL。
下面的代码假设你想创建一个用于键盘的 DirectInput 设备:
LPDIRECTINPUTDEVICE8 keyboardDevice; HRESULT hr = directInputObject ->CreateDevice( GUID_SysKeyboard, &keyboardDevice, 0 ); if FAILED(hr) { return false; }
3. 如何获得键盘/鼠标的信息?
在你从键盘中读取输入之前,需要以一种简单的方式确定键盘上的哪个键被按下。下面提供宏 KEYDOWN 检查你所查看的键是否按下来简单的返回 TRUE 或 FALSE:
#define KEYDOWN( name, key ) ( name[key] & 0x80 )
一个从键盘上读取输入的例子如下:
#define KEYDOWN( name, key ) ( name[key] & 0x80 ) char buffer[256]; while ( 1 ) { keyboardDevice->GetDeviceState( sizeof( buffer ), ( LPVOID )&buffer ); if( KEYDOWN( buffer, DIK_LEFT ) ) { // Do something with the left arrow } if( KEYDOWN( buffer, DIK_UP ) ) { // Do something with the up arrow } }
一个从鼠标读取按键状态的例子如下:
#define BUTTONDOWN(name, key) ( name.rgbButtons[key] & 0x80 ) curX = 320; curY = 240; while ( 1 ) { mouseDevice->GetDeviceState( sizeof ( mouseState ), (LPVOID) &mouseState ); if( BUTTONDOWN( mouseState, 0 ) ) { // Do something with the first mouse button } if( BUTTONDOWN( mouseState, 1 ) ) { // Do something with the up arrow } curX += mouseState.lX; curY += mouseState.lY; }