Интересное Global HotKeys - Горячие клавиши

r3xq1

Пользователь
Пользователь

r3xq1

Пользователь
Пользователь

Глобальные горячие клавиши работают везде где бы вы не нажали определённые сочетания клавиш, программа их отловит и выполнит необходимый метод вызова.
Код прокомментирован!

C#:
namespace HotKeysWorker
{
    using System;
    using System.Windows.Forms;
    using HotKeysWorker.Helpers;
    using HotKeysWorker.Hotkeys;

    internal static partial class Program
    {
        [STAThread]
        public static void Main()
        {
            Console.Title = "HotKeysWorker by r3xq1";

            // Тут прописываем какие клавиши нужно ловить
            HotKeyManager.RegisterHotKey(Keys.Y, Enums.KeyModifiers.Alt); // Y + Alt
            HotKeyManager.RegisterHotKey(Keys.X, Enums.KeyModifiers.Shift); // X + Shift

            // Это не трогаем.
            HotKeyManager.HotKeyPressed += new EventHandler<HotKeyEventArgs>(HotKeyManager_HotKeyPressed);
            Console.Read();

        }

        // Тут происходит вся магия )

        private static void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
        {
            switch (e.Key)
            {
                case Keys.Y when e?.Modifiers == Enums.KeyModifiers.Alt: OnPressedAltY(); break;
                case Keys.X when e?.Modifiers == Enums.KeyModifiers.Shift: OnPressedShiftX(); break;
            }
        }
      
        // Тут Ваши методы для выполнения после нажатий клавиш

        public static void OnPressedAltY()
        {
            Console.WriteLine("Алё вася ты чё ебанутый такую хуйню делаешь");
            Console.Beep();
        }

        public  static void OnPressedShiftX()
        {
            Console.WriteLine("Нахуя ты магией вне Хогвартса занимаешься?");
            Console.Beep();
        }
    }
}
Создадим папку Helpers и создадим в нём класс NativeMethods.cs

C#:
namespace HotKeysWorker.Helpers
{
    using System;
    using System.Runtime.InteropServices;

    internal static class NativeMethods
    {
        #region HotKeys

        [DllImport("user32", SetLastError = true)]
        public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);

        [DllImport("user32", SetLastError = true)]
        public static extern bool UnregisterHotKey(IntPtr hWnd, int id);

        #endregion
    }
}
В папке Helpers создадим класс Enums.cs

C#:
namespace HotKeysWorker.Helpers
{
    using System;

    public static class Enums
    {
        [Flags]
        public enum KeyModifiers
        {
            Alt = 1,
            Control = 2,
            Shift = 4,
            Windows = 8,
            NoRepeat = 0x4000
        }
    }
}
Теперь создаём папку Hotkeys и запишем в него 3-и класса:

Класс HotKeyEventArgs.cs

C#:
namespace HotKeysWorker.Hotkeys
{
    using System;
    using System.Windows.Forms;
    using static HotKeysWorker.Helpers.Enums;

    public partial class HotKeyEventArgs : EventArgs
    {
        public readonly Keys Key;
        public readonly KeyModifiers Modifiers;

        public HotKeyEventArgs(Keys key, KeyModifiers modifiers)
        {
            this.Key = key;
            this.Modifiers = modifiers;
        }

        public HotKeyEventArgs(IntPtr hotKeyParam)
        {
            this.Key = (Keys)(((uint)hotKeyParam.ToInt64() & 0xffff0000) >> 0x10);
            this.Modifiers = (KeyModifiers)((uint)hotKeyParam.ToInt64() & 0x0000ffff);
        }
    }
}
Класс HotKeyManager.cs

C#:
namespace HotKeysWorker.Hotkeys
{
    using System;
    using System.Threading;
    using System.Windows.Forms;
    using HotKeysWorker.Helpers;

    public static partial class HotKeyManager
    {
        private static volatile MessageWindow _wnd;
        private static volatile IntPtr _hwnd;

        public static event EventHandler<HotKeyEventArgs> HotKeyPressed;

        protected delegate void RegisterHotKeyDelegate(IntPtr hwnd, int id, uint modifiers, uint key);
        protected delegate void UnRegisterHotKeyDelegate(IntPtr hwnd, int id);

        public static int RegisterHotKey(Keys key, Enums.KeyModifiers modifiers)
        {
            _windowReadyEvent.WaitOne();
            _wnd.Invoke(new RegisterHotKeyDelegate(RegisterHotKeyInternal), _hwnd, Interlocked.Increment(ref _id), (uint)modifiers, (uint)key);
            return Interlocked.Increment(ref _id);
        }

        public static void UnregisterHotKey(int id) => _wnd.Invoke(new UnRegisterHotKeyDelegate(UnRegisterHotKeyInternal), _hwnd, id);

        private static void RegisterHotKeyInternal(IntPtr hwnd, int id, uint modifiers, uint key) => NativeMethods.RegisterHotKey(hwnd, id, modifiers, key);

        private static void UnRegisterHotKeyInternal(IntPtr hwnd, int id) => NativeMethods.UnregisterHotKey(_hwnd, id);

        private static void OnHotKeyPressed(HotKeyEventArgs e) => HotKeyPressed?.Invoke(null, e);

        private static readonly ManualResetEvent _windowReadyEvent = new ManualResetEvent(false);

        static HotKeyManager()
        {
            new Thread(() => Application.Run(new MessageWindow()); )) { Name = "MessageLoopThread", IsBackground = true }.Start();
        }

        private static int _id = 0;
    }
}
И класс MessageWindow.cs

C#:
namespace HotKeysWorker.Hotkeys
{
    using System.Windows.Forms;

    public static partial class HotKeyManager
    {
        private class MessageWindow : Form
        {
            public MessageWindow()
            {
                _wnd = this;
                _hwnd = this.Handle;
                _windowReadyEvent.Set();
            }
            protected override void WndProc(ref Message m)
            {
                if (m.Msg == WM_HOTKEY) OnHotKeyPressed(new HotKeyEventArgs(m.LParam));
                base.WndProc(ref m);
            }
            protected override void SetVisibleCore(bool value) => base.SetVisibleCore(false);
            private const int WM_HOTKEY = 0x312;
        }
    }
}
 
Сверху Снизу