MSDN.WhiteKnight - Stack Overflow answers
Ответ на "GetKeyboardState: определение состояния клавиши"
Answer 768514
GetKeyboardState
работает только в случаях, когда сообщение о нажатии клавиши дошло до очереди вашего процесса (т.е., когда ваше окно в фокусе). Для получения состояния клавиши напрямую используется функция GetAsyncKeyState. Она не работает для переключаемых клавиш типа Caps Lock - для них нужно использоватьGetKeyState
(или, в C#Control.IsKeyLocked
, который ее использует).if ((GetAsyncKeyState(VK_CONTROL) & 0x8000) != 0){ //нажата клавиша control }
Если нужно в течение длительного времени отслеживать нажатие каких-то клавиш, лучше использовать Keyboard Hook.
Toggled state - состояние Вкл/Выкл для клавиш типа Caps Lock. Для всех остальных клавиш его значение не определено.
C вызовом
GetKeyboardLayout(0)
похожая проблема - он возвращает раскладку для текущего потока, которая может не соответствовать реальной системной раскладке, если окно свернуто. Надо найти поток текущего активного окна, и брать его раскладку.
Итоговый пример кода (C#):
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; public class Keyboard { public const uint VK_CAPITAL = 0x14; [DllImport("USER32.dll")] public static extern short GetKeyState(int vKey); [DllImport("user32.dll")] public static extern short GetAsyncKeyState(int vKey); [DllImport("user32.dll")] public static extern int ToUnicodeEx( uint wVirtKey, uint wScanCode, byte[] lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszBuff, int cchBuff, uint wFlags, IntPtr dwhkl); [DllImport("user32.dll")] public static extern bool GetKeyboardState(byte[] lpKeyState); [DllImport("user32.dll")] public static extern uint MapVirtualKey( uint uCode, uint uMapType); [DllImport("user32.dll")] public static extern IntPtr GetKeyboardLayout(uint idThread); [DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId); [DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow(); public static string VKCodeToUnicode(uint vkCode) { StringBuilder buf = new StringBuilder(); byte[] keyboardState = new byte[255]; short x; byte y; for (int i = 0; i < 255; i++) { if (i == VK_CAPITAL) { x = GetKeyState(i); } else { x = GetAsyncKeyState(i); } y = 0; if ((x & 0x8000) != 0) y = (byte)(y | 0x80); if ((x & 0x0001) != 0) y = (byte)(y | 0x01); keyboardState[i] = y; } ToUnicodeEx(vkCode, MapVirtualKey(vkCode, 0), keyboardState, buf, 5, 0, GetKeyboardLayout(GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero))); return buf.ToString(); } }
Content is retrieved from StackExchange API.
Auto-generated by ruso-archive tools.