I\'ve read similar questions around this issue, including Best way to tackle global hotkey processing in C#? and Set global hotkeys using C#. I\'ve also investigated a NuGet pac
You could also use the NativeWindow class. In the example below, I'm also using an ApplicationContext which is a great way to start a "windowless" application:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MyContext());
}
}
public class MyContext : ApplicationContext
{
private MyHotKey hotkeys = null;
public MyContext()
{
hotkeys = new MyHotKey();
hotkeys.HotkeyPressed += new MyHotKey.HotkeyDelegate(hotkeys_HotkeyPressed);
}
private void hotkeys_HotkeyPressed(int ID)
{
switch (ID)
{
case 1001:
MessageBox.Show("Alt-1");
break;
case 1002:
MessageBox.Show("Alt-2");
break;
case 1003: // Alt-Q
Application.Exit();
break;
default:
break;
}
}
}
public class MyHotKey : NativeWindow
{
private const int WM_HOTKEY = 0x0312;
private const int WM_DESTROY = 0x0002;
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
private List<Int32> IDs = new List<int>();
public delegate void HotkeyDelegate(int ID);
public event HotkeyDelegate HotkeyPressed;
public MyHotKey()
{
this.CreateHandle(new CreateParams());
Application.ApplicationExit += new EventHandler(Application_ApplicationExit);
RegisterCombo(1001, 1, (int)Keys.D1);
RegisterCombo(1002, 1, (int)Keys.D2);
RegisterCombo(1003, 1, (int)Keys.Q);
}
private void RegisterCombo(Int32 ID, int fsModifiers, int vlc)
{
if (RegisterHotKey(this.Handle, ID, fsModifiers, vlc))
{
IDs.Add(ID);
}
}
private void Application_ApplicationExit(object sender, EventArgs e)
{
this.DestroyHandle();
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_HOTKEY:
if (HotkeyPressed != null)
{
HotkeyPressed(m.WParam.ToInt32());
}
break;
case WM_DESTROY: // fires when "Application.Exit();" is called
foreach (int ID in IDs)
{
UnregisterHotKey(this.Handle, ID);
}
break;
}
base.WndProc(ref m);
}
}
Just create global kbhook like this
Using RegisterHotkey() is boilerplate to detect a hotkey press. I won't repeat it here, you can easily google sample code from the function name.
It does however require a window, no workaround for that. It just doesn't have to be a visible window. By far the simplest way to create an invisible window is to use a Form class, like you do in any Winforms application, and set ShowInTaskbar = False, WindowState = Minimized, FormBorderStyle = FixedToolWindow. Call RegisterHotkey() in your OnLoad() method override, you'll need the Handle property. Easy peasy.