D3D学习笔记:IDirectInput

IDirectInput

设置DirectInput的步骤:

1.调用DirectInput8Create() 创建IDirectInput8 接口

2.查询设备的GUID (设置游戏杆才会用到)

3.调用IDirectInput8::CreateDevice() 传递一个GUID

HRESULT CreateDevice(

REFGUID rguid,

LPDIRECTINPUTDEVICE * lplpDirectInputDevice,

LPUNKNOWN pUnkOuter

)

默认的鼠标键盘GUID:

GUID_SysKeyboard

The default system keyboard.

GUID_SysMouse

The default system mouse.

4.设置协作等级The cooperative level determines how this instance of the device interacts with other instances of the device and the rest of the system.

HRESULT SetCooperativeLevel(

         HWND hwnd,

         DWORD dwFlags
				

)

5.设置每一个设备的数据格式。数据格式是你想为将要格式化的每个设备的数据格式。调用IDirectInputDevice8::SetDataFormat()

HRESULT SetDataFormat(

         LPCDIDATAFORMAT lpdf
				

)

6.设置你想要的任何设备的性能。用IDirectInputDevice8::SetProperty()获得。
					

HRESULT SetProperty(

         REFGUID rguidProp,

         LPCDIPROPHEADER pdiph
				

)

7.获得每一个设备,将设备同应用程序相关联。调用IDirectInputDevice8::Acquire()

HRESULT Acquire()

8.(可选)通过调用IDirectInputDevice8::Poll()轮询设备,有些设备需要被轮询而不是通过产生中断。
					

HRESULT Poll()

9.调用IDirectInputDevice8::GetDeviceState()从每一个设备获取数据
					

HRESULT GetDeviceState(

                     DWORD cbData,//Size of the buffer in the lpvData parameter, in bytes.

                     LPVOID lpvData//Address of a structure that receives the current state of the device. The format of the data is established by a prior call to the IDirectInputDevice8::SetDataFormat method. )

 

数据采集模式

直接数据模式(Immediate)和缓冲数据模式(Buffered)

创建主DirectInput对象
					

HRESULT DirectInput8Create(

HINSTANCE hinst,//应用程序的实例句柄

DWORD dwVersion,//采用的DirectInput版本号常量,一般用DIRECTINPUT_VERSION

REFIID riidltf,//创建的接口的版本,一般用IID_IDirectInput8

LPVOID * ppvOut,//返回接口指针的地址

LPUNKNOWN punkOuter//COM的集合,一般设为NULL)

例:

代码开始加上:

#pragma comment(lib,"dinput8.lib")

#pragma comment(lib,"dxguid.lib")

#include<dinput.h>

if(FAILED(DirectInput8Create(hInstance,

DIRECTINPUT_VERSION,

IID_IDirectInput8,//mark

(void **)&lpdi,NULL)

))

:MessageBox(NULL,"FAILED",0,0);

创建设备

        lpdi->CreateDevice(

            GUID_SysKeyboard,//键盘的GUID

            InputDevice,//IDirectInputDevice8 ** InputDevice

            NULL

            );

设置协作等级

协作等级的flags:

DISCL_BACKGROUND

当应用程序在后台或前台激活时都能使用DirectInput设备

DISCL_EXCLUSIVE

一旦获得该设备,其他应用程序都不再能对其申请独占访问。但是其他应用程序依然能够要求非独占地访问它。

DISCL_FOREGROUND

应用程序要求前台访问,获得前台访问后,如果相关窗口被移到后台,则该设备自动化取消。

DISCL_NONEXCLUSIVE

应用程序申请非独占访问,访问该身背将不会干涉其他访问相同设备的应用程序。

DISCL_NOWINKEY

屏蔽window徽标键。

注:键盘必须工作在非独占模式下。

例:

if(FAILED((*InputDevice)->SetCooperativeLevel(hwnd,DISCL_NOWINKEY | DISCL_BACKGROUND)));

Applications must specify either DISCL_FOREGROUND or DISCL_BACKGROUND; it is an error to specify both or neither. Similarly, applications must specify either DISCL_EXCLUSIVE or DISCL_NONEXCLUSIVE.

设置键盘的数据格式

数据格式:

typedef struct DIDATAFORMAT {

    DWORD dwSize;//Size of this structure, in bytes.

    DWORD dwObjSize;//Size of the DIOBJECTDATAFORMAT structure, in bytes.

    DWORD dwFlags;//Flags describing other attributes of the data format. DIDF_ABSAXIS or DIDF_RELAXIS

    DWORD dwDataSize;//Size of a data packet returned by the device, in bytes

    DWORD dwNumObjs;//Number of objects in the rgodf array.

    LPDIOBJECTDATAFORMAT rgodf;//Address to an array of DIOBJECTDATAFORMAT structures

} DIDATAFORMAT, *LPDIDATAFORMAT;

可以使用预设的数据格式

c_dfDIKeyboard 通用键盘

c_dfDIMouse 通用鼠标    

c_dfDIJoystick 通用游戏杆    

c_dfDIJoystick2 通用力反馈

设置数据格式后,DirectInput发送数据包,预定义格式:

DIMOUSESTATE 该数据结构含有鼠标消息

DUOYSTATE 该数据结构含有一个标准游戏杆消息

DUOYSTATE2该数据结构含有一个标准力反馈设备消息

键盘没有预定义的数据结构,可以设为256个字节

例:

    if(FAILED((*InputDevice)->SetDataFormat(&c_dfDIKeyboard)))

                ::MessageBox(NULL,"ERROR",0,0);

获取键盘:

            if(FAILED((*InputDevice)->Acquire()))

                ::MessageBox(NULL,"ERROR",0,0);

读取键盘数据

使用IDirectInputDevice8::GetDeviceState Method

 

当你想归还一个设备时而不释放他,可以调用函数Unacquire()

 

例:

把《Introduction.To.Direct3D9》的例子的输入改为DirectInput

在初始化InitD3D这个函数里:

加上参数IDirectInputDevice8 ** InputDevice

bool d3d::InitD3D(

    HINSTANCE hInstance,

    int width, int height,

    bool windowed,

    D3DDEVTYPE deviceType,

    IDirect3DDevice9** device,

    IDirectInputDevice8 ** InputDevice)

里面内容部分代码:

    //

    // Init D3D:

    //

 

    HRESULT hr = 0;

 

    // Step 1: Create the IDirect3D9 object.

 

    IDirect3D9* d3d9 = 0;

    IDirectInput8 * lpdi = NULL;//mark

    // Step 4: Create the device.

 

    hr = d3d9->CreateDevice(

        D3DADAPTER_DEFAULT, // primary adapter

        deviceType, // device type

        hwnd, // window associated with device

        vp, // vertex processing

     &d3dpp, // present parameters

     device); // return created device

 

    DirectInput8Create(hInstance,DIRECTINPUT_VERSION,IID_IDirectInput8,(void **)&lpdi,NULL);

    lpdi->CreateDevice(

        GUID_SysKeyboard,//键盘的GUID

        InputDevice,//IDirectInputDevice8 ** InputDevice

        NULL);

    if(FAILED((*InputDevice)->SetCooperativeLevel(hwnd,DISCL_NONEXCLUSIVE|DISCL_BACKGROUND)))

    ::MessageBox(NULL,"ERROR1",0,0);

    if(FAILED((*InputDevice)->SetDataFormat(&c_dfDIKeyboard)))

        ::MessageBox(NULL,"ERROR2",0,0);

    if(FAILED((*InputDevice)->Acquire()))

        ::MessageBox(NULL,"ERROR3",0,0);

 

主cpp:

#define DIKEYDOWN(data,n) (data[n] & 0x80)//为了使keystate[DIK_*] & 0x80 方便

在Display函数里:

if( Device && InputDevice )

    {

        //

        // Update the scene: Allow user to rotate around scene.

        //

        InputDevice->GetDeviceState(256,(LPVOID)keystate);

        

        if(DIKEYDOWN(keystate,DIK_UP))

            TheCamera.walk(100.0f * timeDelta);

        if(DIKEYDOWN(keystate,DIK_DOWN))

            TheCamera.walk(-100.0f * timeDelta);

 

        if(DIKEYDOWN(keystate,DIK_LEFT))

            TheCamera.yaw(-1.0f * timeDelta);

        

        if(DIKEYDOWN(keystate,DIK_RIGHT))

            TheCamera.yaw(1.0f * timeDelta);

 

        if(DIKEYDOWN(keystate,DIK_N))

            TheCamera.strafe(-100.0f * timeDelta);

 

        if(DIKEYDOWN(keystate,DIK_M))

            TheCamera.strafe(100.0f * timeDelta);

 

        if(DIKEYDOWN(keystate,DIK_W))

            TheCamera.pitch(1.0f * timeDelta);

 

        if(DIKEYDOWN(keystate,DIK_S))

            TheCamera.pitch(-1.0f * timeDelta);

 

        D3DXMATRIX V;

        TheCamera.getViewMatrix(&V);

        Device->SetTransform(D3DTS_VIEW, &V);

//…………………}

 

重获取

当丢失了设备后,GetDeviceState()函数将返回出错代码:

DIERR_INPUTLOST:设备输入已经丢失。并且在下一次调用时将不能获得。

DIERR_INVALIDPARAM:函数某个参数失效

DIERR_NOTACQUIRED:已经完全失去了该设备

DIERR_NOTINITIALIZED: 设备没准备好

E_PENDING :数据没准备好

例:

        HRESULT result = NULL;

        while(result= InputDevice->GetDeviceState(256,(LPVOID)keystate) == DIERR_INPUTLOST)

        {

            if(FAILED(result = InputDevice->Acquire()))

            {

                break;

            }

        }

        if(FAILED(result))

        {

            //

        }

 

鼠标

和鼠标通信的两种方式:绝对模式(Absolute Mode)和相对模式(Relative Mode),在绝对模式下,鼠标返回鼠标指针所处的位置在屏幕坐标系里的坐标。相对模式下,鼠标返回鼠标相对上个时钟周期以来的相对位移,而不是绝对坐标。

 

控制鼠标的步骤:

  1. 用createDevice()创建鼠标设备
  2. 用SetCooperativeLevel()设置协作等级
  3. 用SetDataFormat()设置数据格式
  4. 用Acquire()获得鼠标
  5. 用GetDeviceState()读取鼠标状态

 

    //创建鼠标设备

    lpdi->CreateDevice(GUID_SysMouse,

        InputDevice,

        NULL);

    if(FAILED((*InputDevice)->SetCooperativeLevel(hwnd,DISCL_BACKGROUND | DISCL_NONEXCLUSIVE)))

        ::MessageBox(NULL,"ERROR_MOUSE",0,0);

    if(FAILED((*InputDevice)->SetDataFormat(*c_dfDIMouse)))

        ::MessageBox(NULL,"ERROR1",0,0);

    if(FAILED((*InputDevice)->Acquire()))

        ::MessageBox(NULL,"ERROR1",0,0);

posted @ 2010-09-13 15:37  xfate  阅读(865)  评论(0编辑  收藏  举报