DirectX Tool Kit: Keyboard and Mouse support


The GamePad abstraction in DirectX Tool Kit was designed to simplify implementing game controller input across the spectrum of platforms supported by DirectX Tool Kit: Windows desktop, Xbox One, Windows 8 Store, and now universal Windows Apps for Windows 10. In a similar vein, the July 2015 release of DirectX Tool Kit includes two new classes for handling keyboard and mouse input across Windows desktop, Windows 8 Store, and universal Windows apps for Windows 10.

Keyboard

The Keyboard class is as usual based on the XNA Game Studio design, with the primary difference being that I needed to use a singleton rather than a static class. As with the XNA Game Studio class, this is intended for using the keyboard as a 'game controller' mapping keys to game input events. To support full text input for chat or text editing, you should make use of the underlying platform's keyboard support to fully handle international input. Integration of the Keyboard class is slightly more complicated than GamePad in that after creating the class instance, you need to make the appropriate calls from either your Win32 message pump for keyboard messages in Windows desktop apps, or you need to provide your application's CoreWindow so that Keyboard can register for the needed callbacks.

For Windows desktop applications, Keyboard takes input from WM_KEYUP, WM_KEYDOWN, WM_SYSKEYUP, and WM_SYSKEYDOWN Win32 messages. For Windows 8 Store and universal Windows apps, it makes use of CoreDispatcher::AcceleratorKeyActivated. As with XNA Game Studio, the Keyboard::State object encodes the virtual keys (rather than scan codes). This works well for most key combinations, but this is a bit quirky when handling Left vs. Right Shift keys (details in the class documentation).

The abstraction makes writing keyboard-based controls quite simple and portable across the supported platforms:

void Game::Update(DX::StepTimer const& timer)
{

auto kb = m_keyboard->GetState();

if (kb.Up || kb.W)
move.y += 1.f;

if (kb.Down || kb.S)
move.y -= 1.f;

if (kb.Left || kb.A)
move.x += 1.f;

if (kb.Right || kb.D)
move.x -= 1.f;
}

See the documentation wiki page on the new class for details, and the related tutorial.

Mouse

The basics of the Mouse class are borrowed from XNA Game Studio, but is also singleton rather than a static class as well as having explicit support for a 'relative' or 'mouse-look' input mode. Integration of the Mouse class is slightly more complicated than GamePad in that you need to make the appropriate calls from either your Win32 message pump for mouse messages in Windows desktop apps, or you need to provide your application's CoreWindow so that Mouse can register for the needed callbacks.

For Windows desktop applications, Mouse uses WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_MOUSEWHEEL, etc. events for handling the default 'absolute' mouse position mode. When in the 'relative' mode, it uses WM_INPUT per the Taking Advantage of High-Definition Mouse Movement article.

For Windows 8 Store and universal Windows apps, Mouse makes use of the standard CoreWindow::PointerMoved, CoreWindow::PointerPressed, etc. events for handling the default 'absolutely' mouse position mode per Responding to touch input (DirectX and C++). For these platforms, the Mouse class also handles the conversion of DIPs to pixels, so be sure to call SetDPI appropriately. When in 'relative' mode, it uses CoreWindow::MouseMoved per Developing mouse controls (DirectX and C++).

The abstraction makes implementing mouse controls simple and reasonably portable between the supported platforms:

void Game::Update(DX::StepTimer const& timer)
{
auto state = g_mouse->GetState();
if (state.positionMode == Mouse::MODE_RELATIVE)
{
// state.x and state.y are relative values; system cursor is not visible
}
else
{
// state.x and state.y are absolute pixel values; system cursor is visible
}

tracker.Update(state);

if (tracker.leftButton == Mouse::ButtonStateTracker::ButtonState::PRESSED)
{
mouse->SetMode(Mouse::MODE_RELATIVE);
}
else if (tracker.leftButton == Mouse::ButtonStateTracker::ButtonState::RELEASED)
{
mouse->SetMode(Mouse::MODE_ABSOLUTE);
}

}

See the documentation wiki page on the new class for details, and the related tutorial.

DirectInput: Developers are strongly discouraged from using legacy DirectInput for handling keyboard and mouse processing as far back as Windows XP. DirectInput should really only be used for supporting legacy HID game controllers and joysticks.

Comments (2)

  1. BM says:

    Thanks for all the great articles. Do you know of one that talks about rendering to an NV12 swap chain directly? Or is there no such support in DirectX?

  2. You can create a NV12 texture with the render target usage–you have to create the special view format aliases for it–but can't use NV12 as display-out format. The only formats supported for swap chains are in the DXGI docs.

Skip to main content