Global hotkeys in windowless .NET app

前端 未结 3 2052
隐瞒了意图╮
隐瞒了意图╮ 2021-01-22 11:06

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

相关标签:
3条回答
  • 2021-01-22 11:42

    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);
        }
    
    }
    
    0 讨论(0)
  • 2021-01-22 11:43

    Just create global kbhook like this

    0 讨论(0)
  • 2021-01-22 11:47

    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.

    0 讨论(0)
提交回复
热议问题