Can't read input from keyboard/mouse using Nuget GameInput lib on PC

gabriel moreau 0 Reputation points
2024-07-18T19:41:51.4866667+00:00

Currently working with the latest version of Microsoft.GameInput version 0.2303.22621.3038.

Using the follwing code, I'm able to read the axis values of a Logitech joystick

IGameInputReading* reading;
if (SUCCEEDED(g_gameInput->GetCurrentReading(GameInputKindController, nullptr, &reading)))
{
	uint32_t count = reading->GetControllerAxisCount();
	std::vector<float> v(count);
	reading->GetControllerAxisState(count, v.data());
	for (uint32_t i = 0; i < count; i++)
	{
		std::cout << "axis " << i << ": " << v[i] << "  ";
	}
	std::cout << std::endl;
	reading->Release();
}

But I'm unable to do the same for a keyboard or a mouse. Here's the code I used for the keyboard

IGameInputReading* reading;
if (SUCCEEDED(g_gameInput->GetCurrentReading(GameInputKindKeyboard, nullptr, &reading)))
{
	uint32_t count = reading->GetKeyCount();
	if (count == 0)
	{
		std::cout << "No key" << std::endl;
	}
	else
	{
		std::vector<GameInputKeyState> v(count);
		reading->GetKeyState(count, v.data());
		for (uint32_t i = 0; i < count; i++)
		{
			std::cout << "Key " << i << ": " << v[i].codePoint << " ";
		}
		std::cout << std::endl;
	}
	device->Release();
	reading->Release();
}

The GetKeyCount function always returns 0 and I also tried to used a fixed buffer and called GetKeyState first, but the function also always returns 0.I'm aware some functionalities like the CreateAggregateDevice are yet to be implemented, is it also the case for keyboard/mouse support?

C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,637 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Castorix31 83,206 Reputation points
    2024-07-18T23:19:29.21+00:00

    This test by copying some parts of MS code (DirectXTK) works for me in a C++/Win32 app :

    (Beep when F8 is pressed)

    #include <windows.h>
    #include <tchar.h>
    
    // C:\Program Files (x86)\Microsoft GDK\231003\GRDK\GameKit\Include
    #include <GameInput.h>
    // C:\Program Files (x86)\Microsoft GDK\231003\GRDK\GameKit\Lib\amd64
    #pragma comment(lib,"gameinput")
    #pragma comment (lib, "xgameruntime")
    
    #pragma comment(linker,"\"/manifestdependency:type='win32' \
    name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
    processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
    
    HINSTANCE hInst;
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    int nWidth = 600, nHeight = 400;
    #define IDC_STATIC 10
    #define IDC_BUTTON 11
    
    IGameInput* m_GameInput;
    bool UpdateApplication();
    
    int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
    {
    	hInst = hInstance;
    	WNDCLASSEX wcex =
    	{
    		sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hInst, LoadIcon(NULL, IDI_APPLICATION),
    		LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_WINDOW + 1), NULL, TEXT("WindowClass"), NULL,
    	};
    	if (!RegisterClassEx(&wcex))
    		return MessageBox(NULL, TEXT("Cannot register class !"), TEXT("Error"), MB_ICONERROR | MB_OK);
    	int nX = (GetSystemMetrics(SM_CXSCREEN) - nWidth) / 2, nY = (GetSystemMetrics(SM_CYSCREEN) - nHeight) / 2;
    	HWND hWnd = CreateWindowEx(0, wcex.lpszClassName, TEXT("Test"), WS_OVERLAPPEDWINDOW, nX, nY, nWidth, nHeight, NULL, NULL, hInst, NULL);
    	if (!hWnd)
    		return MessageBox(NULL, TEXT("Cannot create window !"), TEXT("Error"), MB_ICONERROR | MB_OK);
    	ShowWindow(hWnd, SW_SHOWNORMAL);
    	UpdateWindow(hWnd);
    	/*MSG msg;
    	while (GetMessage(&msg, NULL, 0, 0))
    	{
    		TranslateMessage(&msg);
    		DispatchMessage(&msg);
    	}*/
    
    	do
    	{
    		MSG msg = {};
    		bool done = false;
    		while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
    		{
    			TranslateMessage(&msg);
    			DispatchMessage(&msg);
    
    			if (msg.message == WM_QUIT)
    				done = true;
    		}
    
    		if (done)
    			break;
    	} while (UpdateApplication());	// Returns false to quit loop
    
    	/*TerminateApplication(app);
    	Graphics::Shutdown();*/
    	return 0;
    
    	//return (int)msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	static HWND hWndButton = NULL, hWndStatic = NULL;
    	int wmId, wmEvent;
    	switch (message)
    	{
    	case WM_CREATE:
    	{
    		// hWndStatic = CreateWindowEx(0, TEXT("Static"), TEXT(""), WS_CHILD | WS_VISIBLE | SS_BITMAP, 10, 10, 200, 200, hWnd, (HMENU)IDC_STATIC, hInst, NULL);
    		hWndButton = CreateWindowEx(0, L"Button", L"Click", WS_CHILD | WS_VISIBLE | BS_PUSHLIKE, 100, 60, 60, 32, hWnd, (HMENU)IDC_BUTTON, hInst, NULL);
    		HRESULT hr = GameInputCreate(&m_GameInput);
    		return 0;
    	}
    	break;
    	case WM_COMMAND:
    	{
    		wmId = LOWORD(wParam);
    		wmEvent = HIWORD(wParam);
    		switch (wmId)
    		{
    		case IDC_BUTTON:
    		{
    			if (wmEvent == BN_CLICKED)
    			{
    				Beep(1000, 10);
    			}
    		}
    		break;
    		default:
    			return DefWindowProc(hWnd, message, wParam, lParam);
    		}
    	}
    	break;
    	case WM_PAINT:
    	{
    		PAINTSTRUCT ps;
    		HDC hDC = BeginPaint(hWnd, &ps);
    
    		EndPaint(hWnd, &ps);
    	}
    	break;
    	case WM_DESTROY:
    	{
    		PostQuitMessage(0);
    		return 0;
    	}
    	break;
    	default:
    		return DefWindowProc(hWnd, message, wParam, lParam);
    	}
    	return 0;
    }
    
    // https://github.com/microsoft/DirectXTK/blob/main/Src/Keyboard.cpp
    
    enum Keys : unsigned char
    {
        None = 0,
    
        Back = 0x8,
        Tab = 0x9,
    
        Enter = 0xd,
    
        Pause = 0x13,
        CapsLock = 0x14,
        Kana = 0x15,
        ImeOn = 0x16,
    
        Kanji = 0x19,
    
        ImeOff = 0x1a,
        EscapeKey = 0x1b,
        ImeConvert = 0x1c,
        ImeNoConvert = 0x1d,
    
        Space = 0x20,
        PageUp = 0x21,
        PageDown = 0x22,
        End = 0x23,
        Home = 0x24,
        Left = 0x25,
        Up = 0x26,
        Right = 0x27,
        Down = 0x28,
        Select = 0x29,
        Print = 0x2a,
        Execute = 0x2b,
        PrintScreen = 0x2c,
        Insert = 0x2d,
        Delete = 0x2e,
        Help = 0x2f,
        D0 = 0x30,
        D1 = 0x31,
        D2 = 0x32,
        D3 = 0x33,
        D4 = 0x34,
        D5 = 0x35,
        D6 = 0x36,
        D7 = 0x37,
        D8 = 0x38,
        D9 = 0x39,
    
        A = 0x41,
        B = 0x42,
        C = 0x43,
        D = 0x44,
        E = 0x45,
        F = 0x46,
        G = 0x47,
        H = 0x48,
        I = 0x49,
        J = 0x4a,
        K = 0x4b,
        L = 0x4c,
        M = 0x4d,
        N = 0x4e,
        O = 0x4f,
        P = 0x50,
        Q = 0x51,
        R = 0x52,
        S = 0x53,
        T = 0x54,
        U = 0x55,
        V = 0x56,
        W = 0x57,
        X = 0x58,
        Y = 0x59,
        Z = 0x5a,
        LeftWindows = 0x5b,
        RightWindows = 0x5c,
        Apps = 0x5d,
    
        SleepKey = 0x5f,
        NumPad0 = 0x60,
        NumPad1 = 0x61,
        NumPad2 = 0x62,
        NumPad3 = 0x63,
        NumPad4 = 0x64,
        NumPad5 = 0x65,
        NumPad6 = 0x66,
        NumPad7 = 0x67,
        NumPad8 = 0x68,
        NumPad9 = 0x69,
        Multiply = 0x6a,
        Add = 0x6b,
        Separator = 0x6c,
        Subtract = 0x6d,
    
        Decimal = 0x6e,
        Divide = 0x6f,
        F1 = 0x70,
        F2 = 0x71,
        F3 = 0x72,
        F4 = 0x73,
        F5 = 0x74,
        F6 = 0x75,
        F7 = 0x76,
        F8 = 0x77,
        F9 = 0x78,
        F10 = 0x79,
        F11 = 0x7a,
        F12 = 0x7b,
        F13 = 0x7c,
        F14 = 0x7d,
        F15 = 0x7e,
        F16 = 0x7f,
        F17 = 0x80,
        F18 = 0x81,
        F19 = 0x82,
        F20 = 0x83,
        F21 = 0x84,
        F22 = 0x85,
        F23 = 0x86,
        F24 = 0x87,
    
        NumLock = 0x90,
        Scroll = 0x91,
    
        LeftShift = 0xa0,
        RightShift = 0xa1,
        LeftControl = 0xa2,
        RightControl = 0xa3,
        LeftAlt = 0xa4,
        RightAlt = 0xa5,
        BrowserBack = 0xa6,
        BrowserForward = 0xa7,
        BrowserRefresh = 0xa8,
        BrowserStop = 0xa9,
        BrowserSearch = 0xaa,
        BrowserFavorites = 0xab,
        BrowserHome = 0xac,
        VolumeMute = 0xad,
        VolumeDown = 0xae,
        VolumeUp = 0xaf,
        MediaNextTrack = 0xb0,
        MediaPreviousTrack = 0xb1,
        MediaStop = 0xb2,
        MediaPlayPause = 0xb3,
        LaunchMail = 0xb4,
        SelectMedia = 0xb5,
        LaunchApplication1 = 0xb6,
        LaunchApplication2 = 0xb7,
    
        OemSemicolon = 0xba,
        OemPlus = 0xbb,
        OemComma = 0xbc,
        OemMinus = 0xbd,
        OemPeriod = 0xbe,
        OemQuestion = 0xbf,
        OemTilde = 0xc0,
    
        OemOpenBrackets = 0xdb,
        OemPipe = 0xdc,
        OemCloseBrackets = 0xdd,
        OemQuotes = 0xde,
        Oem8 = 0xdf,
    
        OemBackslash = 0xe2,
    
        ProcessKey = 0xe5,
    
        OemCopy = 0xf2,
        OemAuto = 0xf3,
        OemEnlW = 0xf4,
    
        Attn = 0xf6,
        Crsel = 0xf7,
        Exsel = 0xf8,
        EraseEof = 0xf9,
        Play = 0xfa,
        Zoom = 0xfb,
    
        Pa1 = 0xfd,
        OemClear = 0xfe,
    };
    
    struct State
    {
        bool Reserved0 : 8;
        bool Back : 1;              // VK_BACK, 0x8
        bool Tab : 1;               // VK_TAB, 0x9
        bool Reserved1 : 3;
        bool Enter : 1;             // VK_RETURN, 0xD
        bool Reserved2 : 2;
        bool Reserved3 : 3;
        bool Pause : 1;             // VK_PAUSE, 0x13
        bool CapsLock : 1;          // VK_CAPITAL, 0x14
        bool Kana : 1;              // VK_KANA, 0x15
        bool ImeOn : 1;             // VK_IME_ON, 0x16
        bool Reserved4 : 1;
        bool Reserved5 : 1;
        bool Kanji : 1;             // VK_KANJI, 0x19
        bool ImeOff : 1;            // VK_IME_OFF, 0X1A
        bool Escape : 1;            // VK_ESCAPE, 0x1B
        bool ImeConvert : 1;        // VK_CONVERT, 0x1C
        bool ImeNoConvert : 1;      // VK_NONCONVERT, 0x1D
        bool Reserved7 : 2;
        bool Space : 1;             // VK_SPACE, 0x20
        bool PageUp : 1;            // VK_PRIOR, 0x21
        bool PageDown : 1;          // VK_NEXT, 0x22
        bool End : 1;               // VK_END, 0x23
        bool Home : 1;              // VK_HOME, 0x24
        bool Left : 1;              // VK_LEFT, 0x25
        bool Up : 1;                // VK_UP, 0x26
        bool Right : 1;             // VK_RIGHT, 0x27
        bool Down : 1;              // VK_DOWN, 0x28
        bool Select : 1;            // VK_SELECT, 0x29
        bool Print : 1;             // VK_PRINT, 0x2A
        bool Execute : 1;           // VK_EXECUTE, 0x2B
        bool PrintScreen : 1;       // VK_SNAPSHOT, 0x2C
        bool Insert : 1;            // VK_INSERT, 0x2D
        bool Delete : 1;            // VK_DELETE, 0x2E
        bool Help : 1;              // VK_HELP, 0x2F
        bool D0 : 1;                // 0x30
        bool D1 : 1;                // 0x31
        bool D2 : 1;                // 0x32
        bool D3 : 1;                // 0x33
        bool D4 : 1;                // 0x34
        bool D5 : 1;                // 0x35
        bool D6 : 1;                // 0x36
        bool D7 : 1;                // 0x37
        bool D8 : 1;                // 0x38
        bool D9 : 1;                // 0x39
        bool Reserved8 : 6;
        bool Reserved9 : 1;
        bool A : 1;                 // 0x41
        bool B : 1;                 // 0x42
        bool C : 1;                 // 0x43
        bool D : 1;                 // 0x44
        bool E : 1;                 // 0x45
        bool F : 1;                 // 0x46
        bool G : 1;                 // 0x47
        bool H : 1;                 // 0x48
        bool I : 1;                 // 0x49
        bool J : 1;                 // 0x4A
        bool K : 1;                 // 0x4B
        bool L : 1;                 // 0x4C
        bool M : 1;                 // 0x4D
        bool N : 1;                 // 0x4E
        bool O : 1;                 // 0x4F
        bool P : 1;                 // 0x50
        bool Q : 1;                 // 0x51
        bool R : 1;                 // 0x52
        bool S : 1;                 // 0x53
        bool T : 1;                 // 0x54
        bool U : 1;                 // 0x55
        bool V : 1;                 // 0x56
        bool W : 1;                 // 0x57
        bool X : 1;                 // 0x58
        bool Y : 1;                 // 0x59
        bool Z : 1;                 // 0x5A
        bool LeftWindows : 1;       // VK_LWIN, 0x5B
        bool RightWindows : 1;      // VK_RWIN, 0x5C
        bool Apps : 1;              // VK_APPS, 0x5D
        bool Reserved10 : 1;
        bool Sleep : 1;             // VK_SLEEP, 0x5F
        bool NumPad0 : 1;           // VK_NUMPAD0, 0x60
        bool NumPad1 : 1;           // VK_NUMPAD1, 0x61
        bool NumPad2 : 1;           // VK_NUMPAD2, 0x62
        bool NumPad3 : 1;           // VK_NUMPAD3, 0x63
        bool NumPad4 : 1;           // VK_NUMPAD4, 0x64
        bool NumPad5 : 1;           // VK_NUMPAD5, 0x65
        bool NumPad6 : 1;           // VK_NUMPAD6, 0x66
        bool NumPad7 : 1;           // VK_NUMPAD7, 0x67
        bool NumPad8 : 1;           // VK_NUMPAD8, 0x68
        bool NumPad9 : 1;           // VK_NUMPAD9, 0x69
        bool Multiply : 1;          // VK_MULTIPLY, 0x6A
        bool Add : 1;               // VK_ADD, 0x6B
        bool Separator : 1;         // VK_SEPARATOR, 0x6C
        bool Subtract : 1;          // VK_SUBTRACT, 0x6D
        bool Decimal : 1;           // VK_DECIMANL, 0x6E
        bool Divide : 1;            // VK_DIVIDE, 0x6F
        bool F1 : 1;                // VK_F1, 0x70
        bool F2 : 1;                // VK_F2, 0x71
        bool F3 : 1;                // VK_F3, 0x72
        bool F4 : 1;                // VK_F4, 0x73
        bool F5 : 1;                // VK_F5, 0x74
        bool F6 : 1;                // VK_F6, 0x75
        bool F7 : 1;                // VK_F7, 0x76
        bool F8 : 1;                // VK_F8, 0x77
        bool F9 : 1;                // VK_F9, 0x78
        bool F10 : 1;               // VK_F10, 0x79
        bool F11 : 1;               // VK_F11, 0x7A
        bool F12 : 1;               // VK_F12, 0x7B
        bool F13 : 1;               // VK_F13, 0x7C
        bool F14 : 1;               // VK_F14, 0x7D
        bool F15 : 1;               // VK_F15, 0x7E
        bool F16 : 1;               // VK_F16, 0x7F
        bool F17 : 1;               // VK_F17, 0x80
        bool F18 : 1;               // VK_F18, 0x81
        bool F19 : 1;               // VK_F19, 0x82
        bool F20 : 1;               // VK_F20, 0x83
        bool F21 : 1;               // VK_F21, 0x84
        bool F22 : 1;               // VK_F22, 0x85
        bool F23 : 1;               // VK_F23, 0x86
        bool F24 : 1;               // VK_F24, 0x87
        bool Reserved11 : 8;
        bool NumLock : 1;           // VK_NUMLOCK, 0x90
        bool Scroll : 1;            // VK_SCROLL, 0x91
        bool Reserved12 : 6;
        bool Reserved13 : 8;
        bool LeftShift : 1;         // VK_LSHIFT, 0xA0
        bool RightShift : 1;        // VK_RSHIFT, 0xA1
        bool LeftControl : 1;       // VK_LCONTROL, 0xA2
        bool RightControl : 1;      // VK_RCONTROL, 0xA3
        bool LeftAlt : 1;           // VK_LMENU, 0xA4
        bool RightAlt : 1;          // VK_RMENU, 0xA5
        bool BrowserBack : 1;       // VK_BROWSER_BACK, 0xA6
        bool BrowserForward : 1;    // VK_BROWSER_FORWARD, 0xA7
        bool BrowserRefresh : 1;    // VK_BROWSER_REFRESH, 0xA8
        bool BrowserStop : 1;       // VK_BROWSER_STOP, 0xA9
        bool BrowserSearch : 1;     // VK_BROWSER_SEARCH, 0xAA
        bool BrowserFavorites : 1;  // VK_BROWSER_FAVORITES, 0xAB
        bool BrowserHome : 1;       // VK_BROWSER_HOME, 0xAC
        bool VolumeMute : 1;        // VK_VOLUME_MUTE, 0xAD
        bool VolumeDown : 1;        // VK_VOLUME_DOWN, 0xAE
        bool VolumeUp : 1;          // VK_VOLUME_UP, 0xAF
        bool MediaNextTrack : 1;    // VK_MEDIA_NEXT_TRACK, 0xB0
        bool MediaPreviousTrack : 1;// VK_MEDIA_PREV_TRACK, 0xB1
        bool MediaStop : 1;         // VK_MEDIA_STOP, 0xB2
        bool MediaPlayPause : 1;    // VK_MEDIA_PLAY_PAUSE, 0xB3
        bool LaunchMail : 1;        // VK_LAUNCH_MAIL, 0xB4
        bool SelectMedia : 1;       // VK_LAUNCH_MEDIA_SELECT, 0xB5
        bool LaunchApplication1 : 1;// VK_LAUNCH_APP1, 0xB6
        bool LaunchApplication2 : 1;// VK_LAUNCH_APP2, 0xB7
        bool Reserved14 : 2;
        bool OemSemicolon : 1;      // VK_OEM_1, 0xBA
        bool OemPlus : 1;           // VK_OEM_PLUS, 0xBB
        bool OemComma : 1;          // VK_OEM_COMMA, 0xBC
        bool OemMinus : 1;          // VK_OEM_MINUS, 0xBD
        bool OemPeriod : 1;         // VK_OEM_PERIOD, 0xBE
        bool OemQuestion : 1;       // VK_OEM_2, 0xBF
        bool OemTilde : 1;          // VK_OEM_3, 0xC0
        bool Reserved15 : 7;
        bool Reserved16 : 8;
        bool Reserved17 : 8;
        bool Reserved18 : 3;
        bool OemOpenBrackets : 1;   // VK_OEM_4, 0xDB
        bool OemPipe : 1;           // VK_OEM_5, 0xDC
        bool OemCloseBrackets : 1;  // VK_OEM_6, 0xDD
        bool OemQuotes : 1;         // VK_OEM_7, 0xDE
        bool Oem8 : 1;              // VK_OEM_8, 0xDF
        bool Reserved19 : 2;
        bool OemBackslash : 1;      // VK_OEM_102, 0xE2
        bool Reserved20 : 2;
        bool ProcessKey : 1;        // VK_PROCESSKEY, 0xE5
        bool Reserved21 : 2;
        bool Reserved22 : 8;
        bool Reserved23 : 2;
        bool OemCopy : 1;           // 0XF2
        bool OemAuto : 1;           // 0xF3
        bool OemEnlW : 1;           // 0xF4
        bool Reserved24 : 1;
        bool Attn : 1;              // VK_ATTN, 0xF6
        bool Crsel : 1;             // VK_CRSEL, 0xF7
        bool Exsel : 1;             // VK_EXSEL, 0xF8
        bool EraseEof : 1;          // VK_EREOF, 0xF9
        bool Play : 1;              // VK_PLAY, 0xFA
        bool Zoom : 1;              // VK_ZOOM, 0xFB
        bool Reserved25 : 1;
        bool Pa1 : 1;               // VK_PA1, 0xFD
        bool OemClear : 1;          // VK_OEM_CLEAR, 0xFE
        bool Reserved26 : 1;
    
    #ifdef __clang__
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wunknown-warning-option"
    #pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
    #endif
    
        bool __cdecl IsKeyDown(Keys key) const noexcept
        {
            if (key <= 0xfe)
            {
                auto ptr = reinterpret_cast<const uint32_t*>(this);
                const unsigned int bf = 1u << (key & 0x1f);
                return (ptr[(key >> 5)] & bf) != 0;
            }
            return false;
        }
    
        bool __cdecl IsKeyUp(Keys key) const noexcept
        {
            if (key <= 0xfe)
            {
                auto ptr = reinterpret_cast<const uint32_t*>(this);
                const unsigned int bf = 1u << (key & 0x1f);
                return (ptr[(key >> 5)] & bf) == 0;
            }
            return false;
        }
    
    #ifdef __clang__
    #pragma clang diagnostic pop
    #endif
    };
    
    static constexpr size_t c_MaxSimultaneousKeys = 16;
    
    GameInputCallbackToken mDeviceToken;
    
    GameInputKeyState mKeyState[c_MaxSimultaneousKeys];
    
    inline void KeyDown(int key, State& state) noexcept
    {
        if (key < 0 || key > 0xfe)
            return;
    
        auto ptr = reinterpret_cast<uint32_t*>(&state);
    
        const unsigned int bf = 1u << (key & 0x1f);
        ptr[(key >> 5)] |= bf;
    }
    
    inline void KeyUp(int key, State& state) noexcept
    {
        if (key < 0 || key > 0xfe)
            return;
    
        auto ptr = reinterpret_cast<uint32_t*>(&state);
    
        const unsigned int bf = 1u << (key & 0x1f);
        ptr[(key >> 5)] &= ~bf;
    }
    
    void GetState(State& state)
    {
        state = {};
    
        if (!m_GameInput)
            return;
    
        IGameInputReading* reading;
        if (SUCCEEDED(m_GameInput->GetCurrentReading(GameInputKindKeyboard, nullptr, &reading)))
        {
            uint32_t readCount = reading->GetKeyState(c_MaxSimultaneousKeys, mKeyState);
            for (size_t j = 0; j < readCount; ++j)
            {
                int vk = static_cast<int>(mKeyState[j].virtualKey);
    
                // Workaround for known issues with VK_RSHIFT and VK_NUMLOCK
                if (vk == 0)
                {
                    switch (mKeyState[j].scanCode)
                    {
                    case 0xe036: vk = VK_RSHIFT; break;
                    case 0xe045: vk = VK_NUMLOCK; break;
                    default: break;
                    }
                }
    
                KeyDown(vk, state);
            }
        }
    }
    
    State GetState()
    {
        State state;
        GetState(state);
        return state;
    }
    
    class KeyboardStateTracker
    {
    public:
        State released;
        State pressed;
    
    #pragma prefast(suppress : 26495, "reset() performs the initialization")
        KeyboardStateTracker() noexcept
        {
            reset();
        }
    
        void __cdecl Update(const State& state) noexcept;
    
        void __cdecl reset() noexcept;
    
        bool __cdecl IsKeyPressed(Keys key) const noexcept
        {
            return pressed.IsKeyDown(key);
        }
        bool __cdecl IsKeyReleased(Keys key) const noexcept
        {
            return released.IsKeyDown(key);
        }
    
        State __cdecl GetLastState() const noexcept
        {
            return lastState;
        }
    
    public:
        State lastState;
    };
    
    void KeyboardStateTracker::Update(const State& state) noexcept
    {
        auto currPtr = reinterpret_cast<const uint32_t*>(&state);
        auto prevPtr = reinterpret_cast<const uint32_t*>(&lastState);
        auto releasedPtr = reinterpret_cast<uint32_t*>(&released);
        auto pressedPtr = reinterpret_cast<uint32_t*>(&pressed);
        for (auto j = 0u; j < (256 / 32); ++j)
        {
            *pressedPtr = *currPtr & ~(*prevPtr);
            *releasedPtr = ~(*currPtr) & *prevPtr;
    
            ++currPtr;
            ++prevPtr;
            ++releasedPtr;
            ++pressedPtr;
        }
    
        lastState = state;
    }
    
    void KeyboardStateTracker::reset() noexcept
    {
        memset(this, 0, sizeof(KeyboardStateTracker));
    }
    
    KeyboardStateTracker m_tracker;
    
    bool UpdateApplication()
    {
        State state = GetState();
        if (state.Escape)
            return FALSE;
        // To avoid repeat : https://github.com/Microsoft/DirectXTK/wiki/Keyboard#keyboard-state-tracker
        m_tracker.Update(state);
        //if (state.IsKeyDown(F8))
        if (m_tracker.pressed.F8)
            Beep(2000, 10);
        return TRUE;
    }