你可能想要调查一下降低级别并使用Windows钩子来检测键盘事件。这需要P/Invoke到本地方法,但相当简单。你需要的钩子是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将向您提供有关键盘事件的所有信息;其成员的详细信息可以在MSDN上找到。
这种类型的钩子的一个细节是它在注册它的线程上执行,因此请确保注意这一点,并且如果它要执行任何长时间运行的操作,请不要在UI线程上设置它。