Возможно, вам захочется исследовать переход на нижний уровень и использование оконных крючков для обнаружения событий клавиатуры. Для этого требуется P/Invoking в нативных методах, но довольно прямолинейно. Крючок, который вы хотите, - WH_LL_KEYBOARD. Подробности можно найти по адресу: pinvoke.net.
Вы должны были бы немного шаблонный, но это как можно ближе к клавиатуре событий, как вы можете ожидать, чтобы получить:
[StructLayout(LayoutKind.Sequential)]
public struct KBDLLHOOKSTRUCT
{
public uint vkCode;
public uint scanCode;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
public delegate IntPtr LowLevelKeyboardProc(int, IntPtr, KBDLLHOOKSTRUCT);
[DllImport("kernel32.dll")]
public static extern uint GetCurrentThreadId();
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idhook, LowLevelKeyboardProc proc, IntPtr hMod, uint threadId);
[DllImport("user32.dll")]
static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, ref KBDLLHOOKSTRUCT lParam);
public static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (var curProc = Process.GetCurrentProcess())
using (var curMod = curProc.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curMod.ModuleName), 0u);
}
}
public IntPtr MyKeyboardHook(int code, IntPtr wParam, ref KBDLLHOOKSTRUCT keyboardInfo)
{
if (code < 0)
{
return CallNextHookEx(IntPtr.Zero, wParam, ref keyboardInfo);
}
// Do your thing with the keyboard info.
return CallNextHookEx(IntPtr.Zero, code, wParam, ref keyboardInfo);
}
Убедитесь отцепить свой обработчик, когда ваше приложение перестает нуждаясь его. KBDLLHOOKSTRUCT инкапсулирует всю информацию, которую Windows сообщит вам о событии клавиатуры; Детали его членов могут быть found at MSDN.
Одна из деталей этого крючка заключается в том, что он выполняется на потоке, который его зарегистрировал, поэтому убедитесь, что вы это заметили, и не устанавливайте его в потоке пользовательского интерфейса, если он собирается сделать что- Бег.
У меня нет решения для вас, но могу сказать, что многопоточность - это НЕ ответ. Все события KeyDown обрабатываются в основном (UI) потоке. –
Это может быть аппаратное ограничение на клавиатуре. Работает ли она, когда вы нажимаете одну клавишу, а другая нажимается, когда вы печатаете документ? –
Вы пытались использовать keydown и keyup вместо этого и «запоминаете», какие клавиши находятся в состоянии «вниз»? – Patrick