16

我正在开发 C++ DirectX 2D 游戏,我需要键盘和鼠标输入。
维基百科说:

Microsoft 建议新应用程序使用 Windows 消息循环进行键盘和鼠标输入,而不是 DirectInput

那么我应该如何使用它呢?
我有一个 GameScreen 类负责绘图和更新(游戏逻辑),我在 Windows 消息循环中调用 Draw 和 Update 方法。

谢谢

4

7 回答 7

14

由于您几乎必须运行消息泵才能拥有一个窗口,因此您也可以使用该泵来处理键盘和鼠标输入。是否将键盘事件交给子窗口完全取决于您的泵,如果您愿意,可以在泵中处理它们。

您的典型消息泵如下所示:

while (GetMessage(&msg, NULL, 0, 0))
{
    if (WM_QUIT == msg.message)
       break;
    TranslateMessage(&msg); // post a WM_CHAR message if this is a WM_KEYDOWN
    DispatchMessage(&msg);  // this sends messages to the msg.hwnd
}

对于游戏,您的泵可能看起来更像这样

while (true)
{
   if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_NOYIELD))
   {
      bool fHandled = false;
      if (msg.message >= WM_MOUSEFIRST && msg.message <= WM_MOUSELAST)
         fHandled = MyHandleMouseEvent(&msg);
      else if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST)
         fHandled = MyHandleKeyEvent(&msg);
      else if (WM_QUIT == msg.message)
         break;

      if ( ! fHandled)
      {
         TranslateMessage(&msg);
         DispatchMessage(&msg);
      }
   }
   else
   {
       // if there are no more messages to handle right now, do some
       // game slice processing.
       //
   }
}

当然,您的实际泵可能会比这更复杂,可能使用 aMsgWaitForMultipleObjects以便即使没有要处理的消息,您也可以定期唤醒,但在有消息时立即唤醒。

于 2010-01-30T00:56:30.303 回答
7

DirectInput 已被弃用,原因很充分。据我所知,它创建了一个额外的线程并仅查询 Windows 的原始输入接口。为了获得最佳性能,我会直接使用原始输入。

如果性能对您来说不是问题(我猜这是当前硬件上的 2D 游戏的情况),请遵循 Microsoft 的建议并使用 John Knoeller 所描述的窗口消息。

于 2010-01-30T13:53:32.953 回答
3

仅供参考:关于 John Knoeller 的回答......一个简单的消息泵看起来像这样:

while (GetMessage(&msg, NULL, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

他包含的 WM_QUIT 测试永远不会为真,因为 GetMessage 在收到 WM_QUIT 时返回零。但是,需要在 PeekMessage 循环中测试 WM_QUIT,因为无论是否返回消息,PeekMessage 都会返回 true/false。由于 GetMessage 会阻塞直到返回消息,所以它可以有不同的返回值。

于 2010-02-18T13:57:33.793 回答
1

如果游戏只有一个窗口,那么据我所知,区别纯粹是口味问题。但是,如果您拥有(或计划拥有,或不能肯定地排除将来拥有)多个窗口的选项,那么 Windows 消息传递可能会令人厌烦。

问题是默认情况下,键盘/鼠标消息仅路由到当前焦点所在的窗口,并且通常在游戏中您希望能够切换焦点(到高分视图、雷达视图上的敌人或其他)并仍然保持交互性. 简单的解决方案是针对每个需要键盘/鼠标输入来直接查询它的模块,而不是依赖于消息转发 - 因此,DirectInput。

当然,我不能对您的具体情况说太多 - 只是我的 2c。

于 2010-01-29T21:30:40.853 回答
1

是的,MSDN 帖子是正确的。使用 Windows 消息,您可以使用多语言支持(对于用户可能使用的任何类型的键盘)/用户的个人设置(鼠标右键而不是左键)等。您必须丢弃这些才能使用 DirectInput/XInput . 仅将这 2 个用于游戏手柄/操纵杆支持。其余的只需使用 Windows 消息。

对于细节,我同意 John Knoeller 的回答。

于 2010-01-30T13:37:22.070 回答
0

特殊情况下使用-only使用directinput

与 getmessage 一起使用的 Windows 消息循环的好处是它使用 0% 的 CPU 使用率。如果您正在执行非处理器密集型的事情,例如等待用户的密钥、从用户那里收集数据(例如在数据库或税务程序中,甚至是文字处理器),那么将 Windows 消息与 getmessage 一起使用是有意义的。我上面所有的程序日期都是用户按键时的过程。

Windows 消息循环处理键所需的全部内容就是切换到该程序。鼠标甚至不需要在窗口中。

特殊情况——使用直接输入

如果您需要: 1) 知道何时按下和释放某个键。您也可能不希望将重复键检测为按键。
2)切换到另一个程序时在后台处理键。

如果以上任何一个为真,则使用直接输入。

如果您只是从用户那里收集数据,那么您将需要使用 sleep 命令来暂停程序的执行。如果程序只是坐在那里等待用户的密钥,您希望程序在任务管理器中的 CPU 使用率为 0%。

使用睡眠功能使程序进入睡眠状态,直到您想要轮询直接输入的键。

因此,如果您正在执行从用户那里收集密钥的简单普通任务,如您所见,直接输入只会浪费编程时间。

于 2015-08-27T07:01:10.027 回答
-1

XInput 绝对是要走的路。低延迟输入对游戏至关重要,而 XInput(在新的 DirectXSDK 中替代 DirectInput)正是为这些用例而设计的。

此外,您还支持开箱即用的游戏控制器、操纵杆等。

于 2010-01-29T22:15:17.010 回答