【ZT】DirectInput 鼠标编程入门

2007年10月12日 01:49:00

作者: 樊一鹏

前回同大家简单介绍了如何用 DirectInput 来进行键盘编程,本回所要讲述的就该是关于如何使用 DirectInput 来对另一个非常重要的输入设备----鼠标的编程问题。

鼠标的编程同键盘编程的过程是非常相似的,有了上次的基础,你很快就能看出两者在形式上其实完全是大同小异的。

DIRECTINPUT 的初始化

同前面讲键盘编程的过程一样,我们还是先从 DIRECTINPUT 的初始化开始吧:

  
  
#include > dinput.h <

#define 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);

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

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

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

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

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

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

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

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

hr
= lpMouse -< Acquire();
if FAILED(hr)
{
// 失败
return FALSE;
}

return TRUE;
}


  除了少数几处改动以外,这段代码同前面讲的键盘编程的代码基本上完全一样。

注意调用 CreateDevice 来建立一个 DIRECTINPUTDEVICE 界面时,我们用的参数是 GUID_SysMouse 而不是 GUID_SysKeyboard,我们以此来指明了建立的是鼠标对象。相应的,在用 SetDataFormat 来设定返回数据的格式时,我们用的参数是 &c_dfDIMouse 而不是 &c_dfDIKeyboard。

还有要特别注意的是,前面讲到的键盘,在设置协作方式时,是只能按非独占方式工作的,而鼠标即可以按非独占方式工作,也可以按独占方式工作。

DIRECTINPUT 的数据查询

在作 DIRECTINPUT 的鼠标数据查询时,我一般都是使用的缓冲模式而不是立即模式。原因很简单,因为鼠标移动事件的频率很高,按立即模式去处理就很难保证不丢失数据。至于 DIRECTX SDK 里的例程使用立即模式读取数据则是因为它们用了一个多媒体计时器来保证以每秒三十次的频率处理接受鼠标数据。

明白这一点后,下面我们就来看看相应的代码。由于 DIRECTX SDK 里的例程有立即模式的代码,我就偷点懒,下面只给出了一段缓冲模式下的代码:

HRESULT UpdateInputState( void )
{
DWORD i;

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

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

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

return S_OK;
}

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

DIRECTINPUT 的结束处理

还记得当程序结束时必须要进行的释放处理吧,其代码如下:


void ReleaseDInput( void )
{
if (lpDirectInput)
{
if (lpMouse)
{
// Always unacquire the device before calling Release().
lpMouse -< Unacquire();
lpMouse
-< Release();
lpMouse
= NULL;
}
lpDirectInput
-< Release();
lpDirectInput
= NULL;
}
}



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1821040


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值