Что мне следует использовать: DirectInput или цикл сообщений Windows?

Я работаю над 2D-игрой C ++ DirectX, и мне нужен ввод с клавиатуры и мыши.
Википедия говорит:

Microsoft рекомендует, чтобы новые приложения использовали цикл сообщений Windows для ввода с клавиатуры и мыши вместо DirectInput.

Итак, как мне его использовать?
У меня есть класс GameScreen, который заботится о рисовании и обновлении (игровая логика), я вызываю методы Draw и Update внутри цикла сообщений Windows.

Спасибо


person Adir    schedule 29.01.2010    source источник


Ответы (7)


Поскольку вам в значительной степени нужно запустить насос сообщений, чтобы получить окно, вы также можете использовать этот насос для обработки ввода с клавиатуры и мыши. Передача событий клавиатуры дочернему окну полностью зависит от вашей помпы; вы можете обрабатывать их в помпе, если хотите.

Типичный насос сообщений выглядит так:

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, чтобы вы могли периодически просыпаться, даже если нет сообщений для обработки, но сразу же, когда есть сообщения.

person John Knoeller    schedule 30.01.2010
comment
Я хотел бы знать, почему бы мне не использовать DirectInput. Спасибо - person Adir; 30.01.2010
comment
Ответил Алекс в stackoverflow.com/questions/2165230/ - person bobobobo; 10.02.2010

DirectInput устарел по уважительным причинам. Насколько я знаю, он создает дополнительный поток и просто запрашивает Windows 'Интерфейс Raw Input. Для лучшей производительности я бы использовал Raw Input напрямую.

Если производительность не является для вас проблемой (и я предполагаю, что это относится к 2D-игре на текущем оборудовании), следуйте советам Microsoft и используйте оконные сообщения, как описано Джоном Кнеллером.

person Alexander Gessler    schedule 30.01.2010
comment
Не могли бы вы дополнительно обосновать только запросы интерфейса Windows Raw Input (возможно, со ссылкой)? - person bobobobo; 10.02.2010

К вашему сведению: ответ Джона Кнеллера ... упрощенный насос сообщений выглядит так:

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

Включенный им тест WM_QUIT НИКОГДА не может быть истинным, потому что GetMessage возвращает ноль при получении WM_QUIT. Однако проверка на WM_QUIT в цикле PeekMessage является обязательной, поскольку PeekMessage возвращает true / false независимо от того, было возвращено сообщение или нет. Поскольку GetMessage блокируется до тех пор, пока не будет возвращено сообщение, оно может иметь другое возвращаемое значение.

person Community    schedule 18.02.2010

Если в игре одно окно, то, насколько я могу судить, различие - дело вкуса. Однако если у вас есть (или вы планируете иметь или не можете с уверенностью исключить возможность наличия в будущем) несколько окон, обмен сообщениями в Windows может стать утомительным.

Проблема в том, что по умолчанию сообщения клавиатуры / мыши направляются только в окно, которое в данный момент находится в фокусе, и, как правило, в играх вы хотите иметь возможность переключать фокус (на вид с высоким счетом, враги на радаре или что-то еще) и при этом поддерживать интерактивность . Простое решение было бы для каждого модуля, который требует ввода с клавиатуры / мыши для прямого запроса, а не полагается на пересылку сообщений - следовательно, DirectInput.

Я, конечно, не могу много рассказать о вашем конкретном сценарии - только мой 2с.

person Ofek Shilon    schedule 29.01.2010
comment
Неправда, что события клавиатуры и мыши попадают в окно фокуса. События клавиатуры отправляются в окно фокуса вашим сообщением (это то, что делает DispatchMessage). События мыши попадают в окно под курсором. - person John Knoeller; 30.01.2010
comment
Правильно. Спасибо! Изначально я прокомментировал только клавиатуру и только потом «исправил» это на клавиатуре / мыши .. - person Ofek Shilon; 31.01.2010

Да, сообщение MSDN верное. Используя сообщения Windows, вы можете использовать многоязычную поддержку (для любого типа клавиатуры, которую может использовать пользователь) / личные настройки пользователя (правая кнопка мыши вместо левой) и т. Д., Которые вы должны отказаться, чтобы использовать DirectInput / XInput . Используйте только эти 2 для поддержки геймпада / джойстика. В остальном просто используйте сообщения Windows.

По поводу деталей я согласен с ответом Джона Кнеллера.

person feal87    schedule 30.01.2010

Используйте только использование прямого ввода при особых обстоятельствах

Цикл сообщений Windows, используемый с getmessage, хорош тем, что он использует 0% использования процессора. Если вы выполняете непроцессорные операции, такие как ожидание ключа от пользователя, сбор данных от пользователя, например, в базе данных, налоговой программе или даже текстовом процессоре, имеет смысл просто использовать сообщение Windows с getmessage. Во всех вышеперечисленных программах дата - это процесс, когда пользователь нажимает клавишу.

Все, что нужно циклу сообщений Windows для обработки ключей, - это переключить эту программу. Мышь даже не обязательно должна находиться в окне.

Особые обстоятельства - используйте прямой ввод

Если вам нужно: 1) знать, когда клавиша нажата и отпущена. Вы также можете не захотеть, чтобы повторяющиеся клавиши определялись как нажатия клавиш.
2) Обработка клавиш в фоновом режиме при переключении на другую программу.

Если одно из вышеперечисленных верно, используйте directinput.

Если вы просто собираете данные от пользователя, вам нужно будет использовать команду sleep, чтобы приостановить выполнение программы. Вы хотите, чтобы программа имела 0% использования процессора в диспетчере задач, если программа просто сидит и ждет ключей от пользователя.

Используйте функцию сна, переводя программу в спящий режим, пока вы не захотите запросить клавиши прямого ввода.

Следовательно, прямой ввод просто тратит время программирования, если вы выполняете простую обычную задачу по сбору ключей от пользователя, как вы можете видеть.

person rauprog    schedule 27.08.2015

XInput - это определенно правильный путь. Ввод с малой задержкой имеет решающее значение для игры, и XInput (замена DirectInput в новых DirectXSDK) предназначен именно для этих случаев использования.

Кроме того, у вас есть поддержка игровых контроллеров, джойстиков и т. Д. Из коробки.

person DarthCoder    schedule 29.01.2010
comment
DirectInput не снижает задержку для событий клавиатуры и мыши. Но это дает вам более согласованную модель ввода, если вы позже захотите поддерживать джойстики и т. Д. - person John Knoeller; 30.01.2010
comment
Вы абсолютно правы, но я имел в виду, что DirectInput (и XInput, который является преемником DInputs) имеет меньшую задержку, чем сообщения Windows. - person DarthCoder; 30.01.2010
comment
Но не для ввода с клавиатуры и мыши. DirectInput - это просто оболочка Win32 API для клавиатуры и мыши. - person John Knoeller; 30.01.2010
comment
Это неправда. Вы правы для DInput 1.0, поскольку это была простая оболочка для ввода win32, но начиная с 2.0 DInput общается напрямую с драйвером. Система обмена сообщениями Windows выполняет предварительную обработку входных данных перед их передачей в приложение (WM_CLICK, WM_DOUBLECLICK и т. Д.), Обрабатывает все требования к фокусу и т. Д. Это основная разница в задержках. - person DarthCoder; 30.01.2010
comment
Кстати. Вы можете найти ссылку на мои утверждения в документации DirectX SDK в разделе Direct X Input - ›Direct Input -› Understanding DirectInput - person DarthCoder; 30.01.2010
comment
Разве XInput не только для контроллеров? Спрашивающий спрашивает о вводе с помощью мыши и клавиатуры. Я заглянул в [MSDN doc] (msdn.microsoft.com/en-us/library/windows/desktop/) и документации по DirectX, и только о контроллере xbox. - person Martin Berger; 19.12.2012