我应该使用DirectInput还是Windows消息循环? 我正在做一个C++ DirectX 2D游戏,需要键盘和鼠标输入。 维基百科说:

我应该使用DirectInput还是Windows消息循环? 我正在做一个C++ DirectX 2D游戏,需要键盘和鼠标输入。 维基百科说:,c++,directx,direct3d,directinput,C++,Directx,Direct3d,Directinput,Microsoft建议新应用程序将Windows消息循环用于键盘和鼠标输入,而不是DirectInput 那么我应该如何使用它呢? 我有一个GameScreen类,负责绘制和更新(游戏逻辑),我在windows消息循环中调用绘制和更新方法 谢谢如果游戏只有一个窗口,那么就我所知,区别纯粹是口味的问题。但是,如果您拥有(或计划拥有,或不能肯定地排除将来拥有)多个窗口,那么windows消息传递可能会变得令人厌烦 问题是,默认情况下,键盘/鼠标消息只发送到当前处于焦点的窗口,通常在游戏中,您希望能够

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

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


谢谢

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

问题是,默认情况下,键盘/鼠标消息只发送到当前处于焦点的窗口,通常在游戏中,您希望能够切换焦点(切换到高分视图、雷达上的敌人视图或其他任何视图)并保持互动性。简单的解决方案将适用于需要键盘/鼠标输入来直接查询的每个模块,而不依赖于消息转发,因此使用DirectInput


当然,我不能对您的具体场景说太多,只说我的2c。

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


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

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

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

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 (GetMessage(&msg, NULL, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}
对于一个游戏,你的泵可能看起来更像这样

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.
       //
   }
}
while(true)
{
if(peek消息(&msg,NULL,0,0,PM_REMOVE | PM_NOYIELD))
{
bool fHandled=false;

如果(msg.message>=WM_MOUSEFIRST&&msg.message=WM_KEYFIRST&&msg.message是,则MSDN post是正确的。使用windows消息,您可以使用多语言支持(用户可能使用的任何键盘)/用户的个人设置(鼠标右键而不是左键),等等。为了使用DirectInput/XInput,您必须将其丢弃。 仅将这2个用于gamepad/操纵杆支持。其余仅使用windows消息


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

DirectInput被弃用是有充分理由的。据我所知,它创建了一个额外的线程,只是查询Windows界面。为了获得最佳性能,我会直接使用原始输入


如果性能不是您的问题(我想当前硬件上的2D游戏也是如此),请遵循Microsoft的建议,使用John Knoler所描述的窗口消息。

FYI:Re John Knoler的答案……一个简单的消息泵如下所示:

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 (GetMessage(&msg, NULL, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

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

在特殊情况下仅使用directinput

与getmessage一起使用的Windows消息循环的优点是它使用了0%的cpu使用率。如果您正在执行未处理或密集型操作,例如等待用户的密钥,从用户收集数据,例如在数据库或税务程序中,甚至在字处理程序中,则只需将Windows消息与getmessage一起使用是有意义的。I以上所有程序的日期都是用户按键的过程

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

特殊情况下使用directinput

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

如果以上任一项为真,则使用directinput

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

使用“睡眠”功能将程序置于睡眠状态,直到您想要轮询按键的直接输入


因此,如果您要执行从用户处收集按键的简单普通任务,直接输入只会浪费编程时间。

DirectInput并没有降低键盘和鼠标事件的延迟。但如果您以后想支持操纵杆等,它确实会为您提供更一致的输入模型。您完全正确,但我的意思是那是DirectInput(还有XInput,它是DInputs的继承者)延迟低于Windows消息。但不适用于键盘和鼠标输入。DirectInput只是用于键盘和鼠标的Win32 API的包装器。事实并非如此。对于DInput 1.0,您是正确的,因为它是用于Win32输入的简单包装器,但因为2.0 DInput直接与驱动程序对话。Windows消息传递系统执行pr在输入数据传递到应用程序(WM_CLICK、WM_DOUBLECLICK等)之前对其进行电子处理,处理所有焦点要求等。这是延迟差异主要来自.Btw。您可以在DirectX SDK文档中的“Direct X input->Direct input->Understanding DirectInput”中找到对我声明的引用键盘和鼠标事件不会进入焦点窗口。键盘事件由消息发送到焦点窗口