我应该使用DirectInput还是Windows消息循环?

时间:2010-01-29 21:18:58

标签: c++ directx direct3d directinput

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

  

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

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

由于

7 个答案:

答案 0 :(得分: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.
       //
   }
}

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

答案 1 :(得分:5)

DirectInput已被弃用,原因很充分。据我所知,它创建了一个额外的线程,只是查询Windows'Raw Input界面。为了获得最佳性能,我将直接使用Raw Input。

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

答案 2 :(得分: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会阻塞,直到返回一条消息,因此它可以有不同的返回值。

答案 3 :(得分:1)

如果游戏只有一个窗口,那么就我所知,这种区别纯粹是一种品味问题。但是,如果你已经(或者计划拥有或者不能积极排除将来拥有多个窗口的选项),那么Windows消息传递可能会让人厌烦。

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

我当然不能说你的具体情况 - 只是我的2c。

答案 4 :(得分:1)

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

详情我同意John Knoeller的回答。

答案 5 :(得分:0)

在特殊情况下使用“仅使用直接输入”

与getmessage一起使用的Windows消息循环的好处是它使用0%的cpu使用率。如果您正在进行非处理器密集型操作,例如等待用户输入密钥,从用户收集数据(如数据库或税务程序),甚至是文字处理程序,那么只需将Windows消息与getmessage一起使用即可。我所有上述程序日期都是用户按键时的过程。

Windows消息循环需要处理密钥的所有内容都是为了切换到该程序。鼠标甚至不需要在窗口中。

特殊情况 - 使用directinput

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

如果上述任何一种情况属实,则使用directinput。

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

使用sleep函数将程序置于睡眠状态,直到您想要轮询直接输入键为止。

因此,直接输入只会浪费编程时间,如果你正在做一个简单的普通任务,就像你看到的那样从用户那里收集密钥。

答案 6 :(得分:-1)

XInput绝对是最佳选择。低延迟输入对于游戏至关重要,XInput(在新的DirectXSDK中替换DirectInput)专门针对这些用例而设计。

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