533 строки
18 KiB
C++
533 строки
18 KiB
C++
//--------------------------------------------------------------------------------------
|
|
// File: Keyboard.h
|
|
//
|
|
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
//
|
|
// http://go.microsoft.com/fwlink/?LinkId=248929
|
|
// http://go.microsoft.com/fwlink/?LinkID=615561
|
|
//--------------------------------------------------------------------------------------
|
|
|
|
#pragma once
|
|
|
|
#if !defined(USING_XINPUT) && !defined(USING_GAMEINPUT) && !defined(USING_COREWINDOW)
|
|
|
|
#ifdef _GAMING_DESKTOP
|
|
#include <grdk.h>
|
|
#endif
|
|
|
|
#if (defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_GAMES)) || (defined(_GAMING_DESKTOP) && (_GRDK_EDITION >= 220600))
|
|
#define USING_GAMEINPUT
|
|
#elif (defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)) || (defined(_XBOX_ONE) && defined(_TITLE))
|
|
#define USING_COREWINDOW
|
|
#endif
|
|
|
|
#endif // !USING_XINPUT && !USING_GAMEINPUT && !USING_WINDOWS_GAMING_INPUT
|
|
|
|
#if defined(USING_GAMEINPUT) && !defined(_GAMING_XBOX) && defined(_MSC_VER)
|
|
#pragma comment(lib,"gameinput.lib")
|
|
#endif
|
|
|
|
#include <cstdint>
|
|
#include <memory>
|
|
|
|
#ifdef USING_COREWINDOW
|
|
namespace ABI { namespace Windows { namespace UI { namespace Core { struct ICoreWindow; } } } }
|
|
#endif
|
|
|
|
#ifdef __clang__
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wunknown-pragmas"
|
|
#endif
|
|
|
|
|
|
namespace DirectX
|
|
{
|
|
class Keyboard
|
|
{
|
|
public:
|
|
Keyboard() noexcept(false);
|
|
|
|
Keyboard(Keyboard&&) noexcept;
|
|
Keyboard& operator= (Keyboard&&) noexcept;
|
|
|
|
Keyboard(Keyboard const&) = delete;
|
|
Keyboard& operator=(Keyboard const&) = delete;
|
|
|
|
virtual ~Keyboard();
|
|
|
|
enum Keys : unsigned char
|
|
{
|
|
None = 0,
|
|
|
|
Back = 0x8,
|
|
Tab = 0x9,
|
|
|
|
Enter = 0xd,
|
|
|
|
Pause = 0x13,
|
|
CapsLock = 0x14,
|
|
Kana = 0x15,
|
|
ImeOn = 0x16,
|
|
|
|
Kanji = 0x19,
|
|
|
|
ImeOff = 0x1a,
|
|
Escape = 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,
|
|
|
|
Sleep = 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
|
|
};
|
|
|
|
class KeyboardStateTracker
|
|
{
|
|
public:
|
|
State released;
|
|
State pressed;
|
|
|
|
#ifdef _PREFAST_
|
|
#pragma prefast(push)
|
|
#pragma prefast(disable : 26495, "Reset() performs the initialization")
|
|
#endif
|
|
KeyboardStateTracker() noexcept { Reset(); }
|
|
#ifdef _PREFAST_
|
|
#pragma prefast(pop)
|
|
#endif
|
|
|
|
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;
|
|
};
|
|
|
|
// Retrieve the current state of the keyboard
|
|
State __cdecl GetState() const;
|
|
|
|
// Reset the keyboard state
|
|
void __cdecl Reset() noexcept;
|
|
|
|
// Feature detection
|
|
bool __cdecl IsConnected() const;
|
|
|
|
#ifdef USING_COREWINDOW
|
|
void __cdecl SetWindow(ABI::Windows::UI::Core::ICoreWindow* window);
|
|
#ifdef __cplusplus_winrt
|
|
void __cdecl SetWindow(Windows::UI::Core::CoreWindow^ window)
|
|
{
|
|
// See https://msdn.microsoft.com/en-us/library/hh755802.aspx
|
|
SetWindow(reinterpret_cast<ABI::Windows::UI::Core::ICoreWindow*>(window));
|
|
}
|
|
#endif
|
|
#ifdef CPPWINRT_VERSION
|
|
void __cdecl SetWindow(winrt::Windows::UI::Core::CoreWindow window)
|
|
{
|
|
// See https://docs.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/interop-winrt-abi
|
|
SetWindow(reinterpret_cast<ABI::Windows::UI::Core::ICoreWindow*>(winrt::get_abi(window)));
|
|
}
|
|
#endif
|
|
#elif defined(WM_USER)
|
|
static void __cdecl ProcessMessage(UINT message, WPARAM wParam, LPARAM lParam);
|
|
#endif
|
|
|
|
// Singleton
|
|
static Keyboard& __cdecl Get();
|
|
|
|
private:
|
|
// Private implementation.
|
|
class Impl;
|
|
|
|
std::unique_ptr<Impl> pImpl;
|
|
};
|
|
}
|
|
|
|
#ifdef __clang__
|
|
#pragma clang diagnostic pop
|
|
#endif
|