取得键盘输入
DirectX提供了专门的一个类来取得用户的输入。这个类叫做DirectInput。同DirectX其他部分的一样,DirectInput的使用也是以设备对象为中心的。在交互方面DirectInput设备是非常灵活的。当我们创建一个DirectInput设备,我们必须制定设备需要干什么。C#有一个枚举叫做Microsoft.DirectX.DirectInput.SystemGuid,这用来指定设备。幸运的是,在C#里,如果我们指定这个我们使用Microsoft.DirectX.DirectInput,我们使用SystemGuid来引用枚举值。为了创建能与键盘通信的设备,我们使用下面代码:
Device KeyboardDev = new Device( SystemGuid.Keyboard );
一旦我们创建了键盘设备,我们必须按所需的操作方式配置它。包括告诉它怎么与计算机上其他的应用程序协作,以及它提供什么样的数据给我们。首先是一个多功能的成员函数SetCooperativeLevel。此方法需要两个参数:一个到我们程序的主窗口句柄,和一个定义此设备与计算机其余程序怎样协作的许可掩码。窗口句柄必须使用游戏引擎的应用来提供。它创建了窗口,所以我们知道它能提供这个句柄。许可掩码is up to我们。它由表2-1中所列的枚举组合而成。
表2-1 协作级别标志
MICROSOFT.DIRECTX.DIRECTINPUT.COOPERATIVELEVELFLAGS |
Background |
Exclusive |
Foreground |
NonExclusive |
NoWindowsKey |
Background/Foreground 对是互相排斥的,Exclusive/NonExclusive对也是一样。Foreground选项指定只有应用程序得到焦点时(即处于激活状态时)我们才需要数据。Background选项意味着在任何时候我们都需要每一个击键。如果指定了Exclusive,说明我们需要独占。这仍然会失去对键盘的访问,如果另一个应用程序得到了焦点并且也是独占的,但是这是失去键盘访问的唯一情况。NoWindowsKey指明如果键盘上存在Windows徽标键我们需要忽略它。如果我们的游戏运行在全屏下,包括NoWindowsKey标志就非常重要了,因为这个键可能会导致我们的应用程序失去焦点。一个典型的调用如下:
KeyboardDev.SetCooperativeLevel(m_form, CooperativeLevelFlags..NoWindowsKey |
CooperativeLevelFlags.NonExclusive | CooperativeLevelFlags.Foreground);
下一步要做的是指定需要从设备取回的数据。再次,我们为这个方法使用一个枚举值。对于键盘,调用如下:
KeyboardDev.SetDataFormat(DeviceDataFormat.Keyboard);
DeviceDataFormat枚举被所有由DirectInput创建的对象使用。keyboard格式指明我们需要键盘信息,在这里是一个到KeyBoardState类的引用。此类保存了当前哪些键被按下。
至此键盘设备配置完成。在我们能开始取得键盘数据之前要做的最后一件事是取得设备。方法Acquire激活我们配置好的设备。取得键盘数据需要两步。第一,调用设备的方法Poll,它使设备从硬件取得数据。现在设备有了数据,我们简单的做一份拷贝。下面的语句从设备拷贝字节序列到本地,然后我们就可以使用了:
private KeyboardState m_keydata = null;
m_keydata = KeyboardDev.GetCurrentKeyboardState();
检查一个给定按钮的当前状态,我们索引刚才的字节序列,看是否标志位被设置。举例来说,检查键“A”是否被按下,我们使用下面语句:
if ( m_keydata[Key.A] )
当程序退出时,有一些事情需要注意。我们必须从硬件上解开键盘设备。可以通过调用方法Unacquire达到。完成这个普遍的方法是在Dispose方法里放置Unacquire代码。因为C#不会像C++那样看待析构函数,方法Dispose用来显示的执行清除操作,当我们应用在类上。对于C#对象,析构函数在垃圾收集系统决定需要回收某块内存时调用。因为我们无法控制,所以最后是从接口IDisposable使用Dispose。