@@ -40,93 +40,117 @@ namespace vsgWin32
4040 {
4141 uint16_t modifierMask = 0 ;
4242
43- // see https://learn.microsoft.com/en-us/windows/win32/inputdev/about-keyboard-input#keystroke-message-flags
44- WORD keyFlags = HIWORD (lParam);
45- WORD scanCode = LOBYTE (keyFlags); // scan code
46- BOOL isExtendedKey = (keyFlags & KF_EXTENDED ) == KF_EXTENDED ; // extended-key flag, 1 if scancode has 0xE0 prefix
43+ // Get scancode
44+ uint16_t keyFlags = HIWORD (lParam);
45+ uint16_t scanCode = LOBYTE (lParam);
46+ bool isExtendedKey = (keyFlags & KF_EXTENDED ) == KF_EXTENDED ;
4747
4848 if (isExtendedKey)
49+ {
4950 scanCode = MAKEWORD (scanCode, 0xE0 );
51+ }
52+
53+ // Get virtual key code
54+ uint32_t virtualKey = static_cast <uint32_t >(wParam);
55+
56+ // Left and right modofier detection
57+ if (virtualKey == VK_SHIFT )
58+ {
59+ virtualKey = (scanCode == 0x2A ) ? VK_RSHIFT : VK_LSHIFT ;
60+ }
61+ else if (virtualKey == VK_CONTROL )
62+ {
63+ virtualKey = isExtendedKey ? VK_RCONTROL : VK_LCONTROL ;
64+ }
65+ else if (virtualKey == VK_MENU )
66+ {
67+ virtualKey = isExtendedKey ? VK_RMENU : VK_LMENU ;
68+ }
5069
51- uint32_t virtualKey = ::MapVirtualKeyEx (scanCode, MAPVK_VSC_TO_VK_EX , ::GetKeyboardLayout (0 ));
5270 auto itr = _vk2vsg.find (virtualKey);
5371
5472 if (itr == _vk2vsg.end ())
5573 {
56- // What ever the code was in lParam should translate to a Virtual Key that we know of in _vk2vsg
57- // If we cannot find it, we simply return.
5874 return false ;
5975 }
6076
61- // This is the base-key that was pressed. (i.e., the VSG enum of the physical key pressed).
6277 keySymbol = itr->second ;
6378
64- // Look for any modifiers that may be active.
79+ // Get keys state
6580 BYTE keyState[256 ];
66- if (virtualKey == 0 || !::GetKeyboardState (keyState))
67- {
68- // if virtualKey was undefined or we could not get the keyboard state, simply return.
69- return false ;
70- }
7181
72- // If any of the specific left/right modifier keys are active
73- // add the side-independent vsg modifier to the modifier Mask
74- switch (virtualKey)
82+ if (!::GetKeyboardState (keyState))
7583 {
76- case VK_LSHIFT :
77- case VK_RSHIFT :
78- modifierMask |= vsg::KeyModifier::MODKEY_Shift;
79- break ;
80-
81- case VK_LCONTROL :
82- case VK_RCONTROL :
83- modifierMask |= vsg::KeyModifier::MODKEY_Control;
84- break ;
85-
86- case VK_LMENU :
87- case VK_RMENU :
88- modifierMask |= vsg::KeyModifier::MODKEY_Alt;
89- break ;
90-
91- default :
92- virtualKey = static_cast <uint32_t >(wParam);
93- break ;
84+ return false ;
9485 }
9586
96- // Check if caps lock or numlock is toggled.
87+ // Modifier's flags setting
88+ if (keyState[VK_SHIFT ] & 0x80 ) modifierMask |= vsg::KeyModifier::MODKEY_Shift;
89+ if (keyState[VK_CONTROL ] & 0x80 ) modifierMask |= vsg::KeyModifier::MODKEY_Control;
90+ if (keyState[VK_MENU ] & 0x80 ) modifierMask |= vsg::KeyModifier::MODKEY_Alt;
9791 if (keyState[VK_CAPITAL ] & 0x01 ) modifierMask |= vsg::KeyModifier::MODKEY_CapsLock;
9892 if (keyState[VK_NUMLOCK ] & 0x01 ) modifierMask |= vsg::KeyModifier::MODKEY_NumLock;
9993
100- // Check if the modifier keys are down (these are non-toggle keys, so the high-order bit is relevant!)
101- // again, vsg only has a side-independent modifier
102- if (keyState[VK_LSHIFT ] & 0x80 ) modifierMask |= vsg::KeyModifier::MODKEY_Shift;
103- if (keyState[VK_RSHIFT ] & 0x80 ) modifierMask |= vsg::KeyModifier::MODKEY_Shift;
104- if (keyState[VK_LCONTROL ] & 0x80 ) modifierMask |= vsg::KeyModifier::MODKEY_Control;
105- if (keyState[VK_RCONTROL ] & 0x80 ) modifierMask |= vsg::KeyModifier::MODKEY_Control;
106- if (keyState[VK_LMENU ] & 0x80 ) modifierMask |= vsg::KeyModifier::MODKEY_Alt;
107- if (keyState[VK_RMENU ] & 0x80 ) modifierMask |= vsg::KeyModifier::MODKEY_Alt;
108-
109- // This is the final keyModifier
11094 keyModifier = static_cast <vsg::KeyModifier>(modifierMask);
11195
112- // The actual keystroke is what we get after the ::ToAscii call
113- char asciiKey[2 ];
114- int32_t numChars = ::ToAsciiEx (static_cast <UINT >(wParam), scanCode, keyState, reinterpret_cast <WORD *>(asciiKey), 0 , ::GetKeyboardLayout (0 ));
96+ // Get Unicode symbol
97+ wchar_t unicodeChar[2 ] = {0 };
98+ int numChars = ::ToUnicodeEx (virtualKey, scanCode, keyState, unicodeChar, 2 , 0 , ::GetKeyboardLayout (0 ));
99+
115100 if (numChars == 1 )
116101 {
117- // it is indeed an ascii character. 0-127
118- modifiedKeySymbol = static_cast <vsg::KeySymbol>(asciiKey[0 ]);
102+ wchar_t ch = unicodeChar[0 ];
103+
104+ if (ch >= L' A' && ch <= L' Z' )
105+ {
106+ modifiedKeySymbol = static_cast <vsg::KeySymbol>(L' a' + (ch - L' A' ));
107+ }
108+ else if (ch >= L' a' && ch <= L' z' )
109+ {
110+ modifiedKeySymbol = static_cast <vsg::KeySymbol>(ch);
111+ }
112+ else if (ch >= L' 0' && ch <= L' 9' )
113+ {
114+ modifiedKeySymbol = static_cast <vsg::KeySymbol>(ch);
115+ }
116+ else
117+ {
118+ modifiedKeySymbol = mapUnicodeToKeySymbol (ch);
119+ }
119120 }
120121 else
121122 {
122- // otherwise treat the modifiedKeySymbol as the same as the keySymbol.
123123 modifiedKeySymbol = keySymbol;
124124 }
125125
126126 return true ;
127127 }
128128
129129 protected:
130+
131+ // Helper function for Unicode cahracters
132+ vsg::KeySymbol mapUnicodeToKeySymbol (wchar_t ch)
133+ {
134+ switch (ch)
135+ {
136+ case L' ' : return vsg::KEY_Space;
137+ case L' \t ' : return vsg::KEY_Tab;
138+ case L' \r ' : return vsg::KEY_Return;
139+ case L' ,' : return vsg::KEY_Comma;
140+ case L' .' : return vsg::KEY_Period;
141+ case L' /' : return vsg::KEY_Slash;
142+ case L' ;' : return vsg::KEY_Semicolon;
143+ case L' =' : return vsg::KEY_Equals;
144+ case L' -' : return vsg::KEY_Minus;
145+ case L' [' : return vsg::KEY_Leftbracket;
146+ case L' ]' : return vsg::KEY_Rightbracket;
147+ case L' \\ ' : return vsg::KEY_Backslash;
148+ case L' `' : return vsg::KEY_Tilde;
149+ case L' \' ' : return vsg::KEY_Quote;
150+ default : return static_cast <vsg::KeySymbol>(ch);
151+ }
152+ }
153+
130154 VirtualKeyToKeySymbolMap _vk2vsg;
131155 };
132156
0 commit comments