Этот код из моего проекта работает для меня, похоже, мы могли использовать тот же пример:
private static IntPtr _hookId = IntPtr.Zero;
private readonly External.LowLevelKeyboardProc _proc;
public FrmMain()
{
_proc = HookCallback;
_hookId = SetHook(_proc);
InitializeComponent();
}
private static IntPtr SetHook(External.LowLevelKeyboardProc proc)
{
using(var curProcess = Process.GetCurrentProcess())
{
using(var curModule = curProcess.MainModule)
{
return External.SetWindowsHookEx(External.WH_KEYBOARD_LL, proc, External.GetModuleHandle(curModule.ModuleName), 0);
}
}
}
private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
// You can change this to WM_KEYDOWN
if (nCode >= 0 && wParam == (IntPtr)External.WM_KEYUP)
{
// Code you want to run when a button is pressed.
}
return External.CallNextHookEx(_hookId, nCode, wParam, lParam);
}
Кроме того, это мой External
класс.
public static class External
{
public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
public const int WH_KEYBOARD_LL = 13;
public const int WM_KEYDOWN = 0x0100;
public const int WM_KEYUP = 0x0101;
public const uint WM_GETTEXT = 0x0D;
public const uint WM_GETTEXTLENGTH = 0x0E;
public const uint EM_GETSEL = 0xB0;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern uint GetCurrentThreadId();
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetFocus();
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, StringBuilder lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int SendMessage(IntPtr hWnd, uint Msg, out int wParam, out int lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool GetCaretPos(out Point lPoint);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
}
Я читал, что у вас будут проблемы, если вы попытаетесь выполнить эти перехваты из консольного приложения, хотя ваш вызов Application.Run()
должен это исправить.