使用DirectInput:
DirectInput提供一个访问输入设备所需的接口,通过这个接口,我们能够建立设备,列举系统中的设备,或者检查特殊设备的状态。
在建立一个DirectInput对象后,必须建立一个设备,创建的DirectInput设备使你能够获得详细而且准确的输入设备访问信息。
创建完设备之后,你需要访问它们的输入。这个通过进程处理的动作我们叫它“获得设备”。当你获得了一个设备,你将能初始化他,得到它的性能列表,或者读取他的输入信息。
现在你能访问设备,你就需要在每一帧去读取它的输入。
DirectInput对象的创建 DirectInput8Create
HRESULT WINAPI DirectInput8Create(
HINSTANCE hinst, //创建DirectInput对象的应用程序实例句柄
DWORD dwVersion, //应用程序所请求的DirectInput版本。
REFIID riidltf, //请求页面的标识号,默认IID_IDirectInput8
LPVOID *ppvOut, //指向将被创建的DirectInput对象
LPUNKNOWN punkOuter //此参数一般为NULL
);
DirectInput设备的 创建 CreateDevice
HRESULT CreateDevice(
REFGUID rguid, //设备的GUID号
LPDIRECTINPUTDEVICE *lplpDirectInputDevice,//将要创建的设备
LPUNKNOWN pUnkOuter //控制对象的接口地址,一般为NULL
);
下来就要保证从设备得到的返回数据可靠,有效,所以需要建立一个数据格式。
DirectInput数据格式的设定 SetDataFormat
HRESULT SetDataFormat (LPCDIDATAFORMAT lpdf);
里面参数是一个描述设备各种信息的结构体
typedef struct DIDATAFORMAT {
DWORD dwSize; //结构体的大小
DWORD dwObjSize; // LPDIOBJECTDATAFORMAT的大小
DWORD dwFlags; //指定数据格式的属性
DWORD dwDataSize; //从设备返回的数据包大小
DWORD dwNumObjs; // rgodf数组对象的数量
LPDIOBJECTDATAFORMAT rgodf; // LPDIOBJECTDATAFORMAT结构体地址
} DIDATAFORMAT, *LPDIDATAFORMAT;
如果你想使用一个不是标准设备的输入设备,你需要创建并且使用你所拥有的DIDATAFORMAT结构。
一般常用的输入设备的DIDATAFORMAT结构可以直接使用预先定义好的宏:
¤c_dfDIKeyboard 这是一个表示系统键盘对象的数据格式
¤c_dfDIMouse 这个是四键鼠标的数据格式
¤c_dfDIMouse2 这个是八键鼠标的数据格式
如果需要的就是标准,常用的设备,就可以直接找到他的预定义格式使用。
HRESULT hr;
hr = DI_Device->SetDataFormat(&c_dfDIKeyboard);
if FAILED( hr )
return false;
DirectInput设备协调层的设置
SetCooperativeLevel
设备协调层会告诉系统你创建的的输入设备如何跟系统一起工作,你可以设置输入设备是独占的或者非独占的进行访问。
独占访问的意思是只有你的应用程序可以使用这个特定的设备,其他的应用程序不能分享,在全屏游戏模式下非常有用。
HRESULT SetCooperativeLevel(
HWND hwnd, //请求访问设备的窗口句柄
DWORD dwFlags //访问方式标志位的设置
);
dwFlags常用的有:
¤DISCL_BACKGROUND 应用程序请求后台访问设备,意思是说你能够使用输入设备,甚至是游戏窗口不是当前窗口的时候。
¤DISCL_EXCLUSIVE 游戏请求独占输入设备
¤DISCL_FOREGROUND 游戏请求仅当游戏窗口为当前窗口的时候访问设备。
¤DISCL_NONEXCLUSIVE 游戏请求非独占输入设备
¤DISCL_NOWINKEY 甚至屏蔽所有的WINDOWS键,就是当WINDOWS键按下后,游戏仍然保留焦点。
⊙这些标志需要根据实际情况的不同进行组合使用
DI_Device->SetCooperativeLevel( wndHandle,DISCL_FOREGROUND | DISCL_NONEXCLUSIVE );
DirectInput对设备访问的请求
HRESULT Acquire(VOID);
DirectInput获得输入信息
GetDeviceState
在上一步只有一句的重要代码获得了设备,下面就可以进行信息获取了,无论输入设备是键盘,鼠标还是其他所有的,我们获得它们信息的方法是一样的:
HRESULT GetDeviceState(
DWORD cbData, // lpvData内存的大小
LPVOID lpvData // 接受设备当前状态的结构体地址
);
例如:
char Buffer[256];
DI_Device->GetDeviceState(sizeof(buffer),(LPVOID)&buffer);
因为我们所说的都是在有标准设备的前提下进行的,但是有些情况,用户没有我们需要的设备,所以DirectInput需要有一个决定到底系统有多少个,什么类型的输入设备。
Enumerating Input Devices(简)
正象Direct3D能通过在系统中安装的视频卡来列出并且得到它们的性能,DirectInput也能对输入系统做同样的事情。
通过DirectInput对象使用有效的方法,DirectInput能获得系统有效的输入设备的数量,也包括每个设备的类型,功能。
DirectInput是通过IDirectInput8::EnumDevices方法来完成这个任务的。
HRESULT EnumDevices(
DWORD dwDevType,//设备类型
LPDIENUMDEVICESCALLBACK lpCallback, //回调函数
LPVOID pvRef, //向回调函数传递参数,你可以用任意32位值。(NULL)
DWORD dwFlags //标志位
);
dwDevType:这个参数为设备搜寻设置一个过滤器,主要的值有:
∷DI8DEVCLASS_ALL 搜寻所有安装的输入设备
∷DI8DEVCLASS_DEVICE 搜寻所有不属于其他类型的设备
∷DI8DEVCLASS_GAMECTRL 搜寻所有的游戏控制器
∷DI8DEVCLASS_KEYBOARD 搜索所有的键盘
∷DI8DEVCLASS_POINTER 搜索所有的
DI8DEVTYPE_MOUSE&DI8DEVTYPE_SCREENPOINTER类型的设备
dwFlags:让该方法EnumDevices知道列表的范围,例如,如果你想让EnumDevices仅搜索系统安装了的设备,或者有回馈的设备,就需要这里设置说明,相关值如下:
∷DIEDFL_ALLDEVICES 这个是默认值,列出系统所有设备
∷DIEDFL_ATTACHEDONLY 列出当前附属于系统的设备
∷DIEDFL_FORCEFEEDBACK 列出支持回馈的设备
∷DIEDFL_INCLUDEALIASES
∷DIEDFL_INCLUDEHIDDEN 列出系统的隐藏设备
∷DIEDFL_INCLUDEPHANTOMS
例子
HRESULT hr;
hr = DI_Object->EnumDevices( DI8DEVCLASS_GAMECTRL,
EnumJoysticksCallback,NULL,DIEDFL_ATTACHEDONLY ) ;
If FAILED( hr )
return false;
从键盘获得输入信息
从键盘读取数据简单的原因是键盘是一个缺省设备,键盘需要一个256字节的数组:
如:
char buffer[256];
这个字符数组保存键盘上所有按键的状态。
下来的任务就是判断按键,简单的方法是做宏:
#define KEYDOWN(name,key) (name[key] & 0x80)
直接判断然后分别执行就OK了。
从鼠标获得输入信息
鼠标信息的读取和键盘读取类似。主要不同在于GUID和数据格式的不同。
存储鼠标状态的结构体为DIMOUSESTATE(四键消息结构)
支持多输入设备
每个输入设备都要拥有属于自己的DirectInputDevice,所以代码需要支持多个DirectInputDevice。你能做的就是创建一个DirectInputDevice数组或者向量。
下一步是系统中安装的设备列表。当你存储了每个设备的数据后,你就能调用CreateDevice,你需要用为每个你保存了回调函数的设备调用CreateDevice方法,在你创建了所有的设备后,你就能进行所有你想要信息的访问。
Buffer For Hold Keyboard Data
DIPROPDWORD Structure
Syntax :
typedef struct DIPROPDWORD{
DIPROPHEADER diph;
DWORD dwData;
} DIPROPDWORD, *LPDIPROPDWORD ;
typedef const DIPROPWORD *LPCDIPROPDWORD ;
members :
dwData 设置或获得指定的属性
diph 一个DIPROPHEADER结构体
dwSize sizeof(DIPROPDWORD)
dwHearderSize sizeof(DIPROPHEADER)
dwHow 指定应该怎么解释dwObj成员,
dwObj 如果dwHow成员是DIPH_DEVICE,则它必为
0.
如果dwHow成员是DIPH_BYID,则它必须是
一个对象的标识,这个对象的属性设置可以设置或者获得。
相关DIPROPDWORD的操作:
IDirectInputDevice8::SetProperty 设置定义设备行为的属性,这些属性包括输入缓冲大小和“轴”模式。
HRESULT SetProperty ( REFGUID rguidProp,
LPCDIPROPHEADER pdiph);
RguidProp 指示一个GUID的地址,关于键盘缓冲的预定义为:
DIPROP_BUFFERSIZE 设置输入缓冲区大小这个设置将应用于整个设备,所以dwHow成员必须设置DIPH_DEVICE
DIDEVICEOBJECTDATA Structure
结构包含了设备缓冲区信息。
结构在IDirectInputDevice8::GetDeviceData和
IDirectInputDevice8::SendDeviceData方法中用到。
Syntax :
typedef stuct DIDEVICEOBJECTDATA{
DWORD dwOfs;
DWORD dwData;
DWORD dwTimeStamp;
DWORD dwSequence;
UINT_PTR uAppData;
} DIDEVICEOBJECTDATA, *LPDIDEVICEOBJECTDATA;
typedef const DIDEVICEOBJECTDATA *LPCDIDEVICEOBJECTDATA;