directinput:DirectInput 鼠标编程入门

    前回同大家简单介绍了如何用 DirectInput 来进行键盘编程本回所要讲述就该是有关如何使用DirectInp
ut 来对另个非常重要输入设备----鼠标编程问题
  鼠标编程同键盘编程过程是非常相似有了上次基础你很快就能看出两者在形式上其实完全是大同
小异.

1、DIRECTINPUT
  同前面讲键盘编程过程我们还是先从 DIRECTINPUT 化开始吧:
  # <dinput.h>

  # DINPUT_BUFFERSIZE 16

  LPDIRECTINPUT lpDirectInput; // DirectInput object
  LPDIRECTINPUTDEVICE lpMouse; // DirectInput device

  BOOL InitDInput(HWND hWnd)
  {
    HRESULT hr;

    // 创建个 DIRECTINPUT 对象
    hr = DirectInputCreate(hInstanceCopy, DIRECTINPUT_VERSION, &lpDirectInput, NULL);

     FAILED(hr)
    {
     // 失败
      FALSE;
    }

    // 创建个 DIRECTINPUTDEVICE 界面
    hr = lpDirectInput->CreateDevice(GUID_SysMouse, &lpMouse, NULL);
     FAILED(hr)
    {
     // 失败
      FALSE;
    }

    // 设定查询鼠标状态返回数据格式
    hr = lpMouse->SetDataFormat(&c_dfDIMouse);
     FAILED(hr)
    {
     // 失败
      FALSE;
    }

    // 设定协作模式
    hr = lpMouse->SetCooperativeLevel(hWnd,
       DISCL_EXCLUSIVE | DISCL_FOREGROUND);
     FAILED(hr)
    {
     // 失败
      FALSE;
    }

    // 设定缓冲区大小
    // 如果不设定缓冲区大小默认值为 0就只能按立即模式工作
    // 如果要用缓冲模式工作必须使缓冲区大小超过 0
    DIPROPDWORD property;

    property.diph.dwSize = (DIPROPDWORD);
    property.diph.dwHeaderSize = (DIPROPHEADER);
    property.diph.dwObj = 0;
    property.diph.dwHow = DIPH_DEVICE;
    property.dwData = DINPUT_BUFFERSIZE;

    hr = lpMouse->SetProperty(DIPROP_BUFFERSIZE, &property.diph);

     FAILED(hr)
    {
     // 失败
      FALSE;
    }

    hr = lpMouse->Acquire;
     FAILED(hr)
    {
     // 失败
      FALSE;
    }

   TRUE;
  }
  除了少数几处改动以外这段代码同前面讲键盘编程代码基本上完全
  注意 CreateDevice 来建立个 DIRECTINPUTDEVICE 界面时我们用参数是 GUID_SysMouse 而不是 G
UID_SysKeyboard我们以此来指明了建立是鼠标对象相应在用 SetDataFormat 来设定返回数据格式时
我们用参数是 &c_dfDIMouse 而不是 &c_dfDIKeyboard
  还有要特别注意前面讲到键盘在设置协作方式时是只能按非独占方式工作而鼠标即可以按非
独占方式工作也可以按独占方式工作

2、DIRECTINPUT 数据查询
  在作 DIRECTINPUT 鼠标数据查询时般都是使用缓冲模式而不是立即模式原因很简单鼠标
移动事件频率很高 按立即模式去处理就很难保证不丢失数据至于 DIRECTX SDK 里例程使用立即模式读取
数据则是它们用了个多媒体计时器来保证以每秒 3十次频率处理接受鼠标数据
  明白这点后 下面我们就来看看相应代码由于 DIRECTX SDK 里例程有立即模式代码我就偷点懒
下面只给出了段缓冲模式下代码:
  HRESULT UpdateInputState(void)
  {
    DWORD i;

    (lpMouse != NULL)
    {
     DIDEVICEOBJECTDATA didod; // Receives buffered data
     DWORD dwElements;
     HRESULT hr;

     while(TRUE)
     {
      dwElements = 1; // 每次从缓冲区中读个数据
      hr = lpMouse->GetDeviceData((DIDEVICEOBJECTDATA),&didod,&dwElements,0);

       FAILED(hr)
      {
       // 发生了
       (hr DIERR_INPUTLOST)
       {
        hr = lpMouse->Acquire; // 试图重新取回设备
         FAILED(hr)
        {
          S_FALSE; // 失败
        }
       }
      }
      
      (elements 1)
      {
       switch(didod.dwOfs)
       {
         DIMOFS_X: // X 轴偏移量
                // didod.dwData 里是具体偏移相对值单位为像素
          ;
         DIMOFS_Y: // Y 轴偏移量
                // didod.dwData 里是具体偏移相对值单位为像素
          ;
         DIMOFS_BUTTON0: // 0 号键(左键)状态
                   // didod.dwData 里是具体状态值
                   // 低字节最高位为 1 则表示按下
                   // 低字节最高位为 0 表示未按下
          ;
         DIMOFS_BUTTON1: // 1 号键(右键)状态
                   // 同上
          ;
         DIMOFS_BUTTON2: // 2 号键(中键)状态
                   // 同上
          ;
         DIMOFS_BUTTON3: // 3 号键状态
                   // 同上
          ;
       }
      }
       (elements 0) ; // 缓冲区读空
     }
   }

   S_OK;
  }
  这段代码注释得非常详细相信你很快就能看懂

3、DIRECTINPUT 结束处理
  还记得当结束时必须要进行释放处理吧其代码如下:
  void ReleaseDInput(void)
  {
    (lpDirectInput)
   {
    (lpMouse)
    {
     // Always unacquire the device before calling Release.
     lpMouse->Unacquire;
     lpMouse->Release;
     lpMouse = NULL;
    }
    lpDirectInput->Release;
    lpDirectInput = NULL;
   }
  }
Tags:  电脑编程入门 编程入门 directinput

延伸阅读

最新评论

发表评论