views:

853

answers:

6

I'm working on a C++ DirectX 2D game and I need keyboard and mouse input.
Wikipedia says:

Microsoft recommends that new applications make use of the Windows message loop for keyboard and mouse input instead of DirectInput

So how should I use it?
I have a GameScreen class whice take care of the drawing and the updating(game logic), I call the Draw and the Update methods inside a windows message loop.

Thanks

+1  A: 

If the game has a single window, than as far as I can tell the distinction is purely a matter of taste. If however, you have (or are planning to have, or cannot positively rule out the option of having in the future) multiple windows, then windows messaging can get tiresome.

Problem is that by default keyboard/mouse messages are routed only to the window currently in focus, and typically in games you want to be able to switch focus (to a hi-score view, enemies on radar view or whatever) and still maintain interactivity. The easy solution would be for every module which requires keyboard/mouse input to query for it directly, and not rely on message forwarding - hence, DirectInput.

I can't say much about your specific scenario, of course - just my 2c.

Ofek Shilon
It's not true that keyboard and mouse events go to the focus window. Keyboard events are sent to the focus window _by your message pump_ (that's what DispatchMessage does). Mouse events go to the window under the cursor.
John Knoeller
Right. Thanks! I originally commented with keyboard only and only then 'fixed' it to keyboard/mouse..
Ofek Shilon
A: 

XInput is definitly the way to go. Low-Latency input is crucial to gameing and XInput ( replacement of DirectInput in the new DirectXSDKs ) is designed for exactly these use-cases.

Further you have support for gamecontrollers, joysticks, etc out of the box.

DarthCoder
DirectInput is not lower latency for keyboard and mouse events. But it does give you a more consistent input model if you later want to support joysticks, etc.
John Knoeller
You are absolutly right, but what I meant was that DirectInput ( and XInput, which is DInputs successor ) has a lower latency than Windows messages.
DarthCoder
But not for keyboard and mouse input. DirectInput is just a wrapper around the Win32 API for keyboard and mouse.
John Knoeller
That is not true. You are correct for DInput 1.0, as this was a simple wrapper around the win32 input, but since 2.0 DInput talks directly to the driver. The windows messaging system does a preprocessing ofthe input data before it passes it on to the application ( WM_CLICK, WM_DOUBLECLICK, etc ), handles all focus requirements, etc.This is were the latency difference mostly come from.
DarthCoder
Btw. You can find the citation to my claims in the DirectX SDK Documentation in "Direct X Input -> Direct Input -> Understanding DirectInput"
DarthCoder
+3  A: 

Since you pretty much have to run a message pump in order to have a window, you might as well use that pump to handle keyboard and mouse input as well. It's entirely up to your pump whether you hand keyboard events on to a child window, you can handle them in the pump if you prefer.

Your typical message pump looks like this:

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
}

For a game, your pump might look more like this

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.
       //
   }
}

Of course, your actual pump will likely be even more complex than that, possibly with a MsgWaitForMultipleObjects so that you can wake periodically even if there a no messages to process, but immediatelly when there are messages.

John Knoeller
I would like to know why shouldn't I use DirectInput. Thanks
Adir
Answered by Alex in http://stackoverflow.com/questions/2165230/should-i-use-directinput-or-windows-message-loop/2168067#2168067
bobobobo
A: 

Yes, the MSDN post is correct. Using windows messages you can use the multilanguage support (for any kind of keyboard the user may be using)/personal settings of the user (mouse right button instead of left), etc.. that you have to discard away to use DirectInput/XInput. Only use those 2 for the gamepad/joystick support. For the rest just use the windows messages.

For the details i agree with the John Knoeller answer.

feal87
+1  A: 

DirectInput has been deprecated for good reasons. As fas as I know, it creates an extra thread and just queries Windows' Raw Input interface. For best performance, I'd use Raw Input directly.

If performance is not an issue for you (and I guess that's the case for a 2D game on current hardware), follow Microsoft's advice and use window messages, as described by John Knoeller.

Alexander Gessler
Can you please substantiate "just queries Windows' Raw Input interface" bit further (wiht a reference perhaps)?
bobobobo
A: 

FYI: Re John Knoeller's answer... a simplistic message pump looks like this:

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

The WM_QUIT test that he included can NEVER be true because GetMessage returns zero when a WM_QUIT is received. However, testing for WM_QUIT in a PeekMessage loop is required because PeekMessage returns true/false whether a message was returned or not. Since GetMessage blocks until a message is returned, so it can have a different return value.

nurbles