Ответы пользователя по тегу C#
  • Как сделать обработчик нажатия клавиш клавиатуры в неактивной форме?

    NiceHack
    @NiceHack
    Пока что просто прогер
    Хочу уточнить суть вопроса, получается у тебя программа работает в window forms, и ты хочешь чтобы при нажатии определенного сочетания клавиш, она у тебя закрывалась и работала в фоновом режиме, и наоборот также открывалась при сочетании клавиш. Если так, то есть уже готовый класс прямо в window forms, он называется KeyboardHook, просто подключаешь его, вставляешь в код инициализации window forms, где объявляешь его и назначаешь клавиши для него и он будет работать в фоновом режиме и ловить сочетания клавиш, и для него нужно подключать ссылку на библиотеку user32.dll(Он уже встроен в Visual Studio и не надо скачивать стороннюю библиотеку) и только потом его использовать. Надеюсь ты умеешь подключать ссылки на библиотеки. Если нет, то загугли. К слову я работаю в основном на WPF и к нему нельзя подключить эту библиотеку(не знаю почему), только к window forms, и мне приходится вставлять ее вручную как класс(ты тоже можешь не подключать целую библиотеку, а подключить только один класс, скопировать и вставить как свой класс). Вот пример применения этого класса:
    using System.Windows.Input; // Не забудь это.
    // Ну тут просто привязываешь любые клавиши к действию.
    // В первой переменной идет привязка сочетаний клавиш F12 + shift и alt в любом порядке 
    // Важная особенность (но я не проверял) первый аргумент это идет любая клавиша которая будет последней
    // второй и третий уже сочетание клавиш , т.е. shift + alt + F12 или alt + shift + F12.
    var _hotKey1 = new KeyboardHook(Key.F12, KeyModifier.Shift | KeyModifier.Alt, (x) => Show());
    var _hotKey2 = new KeyboardHook(Key.F11, KeyModifier.Shift | KeyModifier.Alt, (x) => Hide());

    А вот она и сама
    // Единственное, я тут поменял все на слово HotKey, для собственного удобства. 
    public class HotKey : IDisposable
        {
            private static Dictionary<int, HotKey> _dictHotKeyToCalBackProc;
    
            [DllImport("user32.dll")]
            private static extern bool RegisterHotKey(IntPtr hWnd, int id, UInt32 fsModifiers, UInt32 vlc);
    
            [DllImport("user32.dll")]
            private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
    
            public const int WmHotKey = 0x0312;
    
            private bool _disposed = false;
    
            public Key Key { get; private set; }
            public KeyModifier KeyModifiers { get; private set; }
            public Action<HotKey> Action { get; private set; }
            public int Id { get; set; }
    
            public HotKey(Key k, KeyModifier keyModifiers, Action<HotKey> action, bool register = true)
            {
                Key = k;
                KeyModifiers = keyModifiers;
                Action = action;
                if (register)
                {
                    Register();
                }
            }
    
            public bool Register()
            {
                int virtualKeyCode = KeyInterop.VirtualKeyFromKey(Key);
                Id = virtualKeyCode + ((int)KeyModifiers * 0x10000);
                bool result = RegisterHotKey(IntPtr.Zero, Id, (UInt32)KeyModifiers, (UInt32)virtualKeyCode);
    
                if (_dictHotKeyToCalBackProc == null)
                {
                    _dictHotKeyToCalBackProc = new Dictionary<int, HotKey>();
                    ComponentDispatcher.ThreadFilterMessage += new ThreadMessageEventHandler(ComponentDispatcherThreadFilterMessage);
                }
    
                _dictHotKeyToCalBackProc.Add(Id, this);
    
                Debug.Print(result.ToString() + ", " + Id + ", " + virtualKeyCode);
                return result;
            }
    
            public void Unregister()
            {
                HotKey hotKey;
                if (_dictHotKeyToCalBackProc.TryGetValue(Id, out hotKey))
                {
                    UnregisterHotKey(IntPtr.Zero, Id);
                }
            }
    
            private static void ComponentDispatcherThreadFilterMessage(ref MSG msg, ref bool handled)
            {
                if (!handled)
                {
                    if (msg.message == WmHotKey)
                    {
                        HotKey hotKey;
    
                        if (_dictHotKeyToCalBackProc.TryGetValue((int)msg.wParam, out hotKey))
                        {
                            if (hotKey.Action != null)
                            {
                                hotKey.Action.Invoke(hotKey);
                            }
                            handled = true;
                        }
                    }
                }
            }
    
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
    
            protected virtual void Dispose(bool disposing)
            {
                if (!this._disposed)
                {
                    if (disposing)
                    {
                        Unregister();
                    }
    
                    _disposed = true;
                }
            }
        }
    
        [Flags]
        public enum KeyModifier
        {
            None = 0x0000,
            Alt = 0x0001,
            Ctrl = 0x0002,
            NoRepeat = 0x4000,
            Shift = 0x0004,
            Win = 0x0008
        }

    Надеюсь я правильно понял твой вопрос и смог тебе помочь. И никаких практически знаний не нужно,
    рассказал все очень подробно, если что задавай вопросы(Предупреждение, возможны ошибки в коде потому что я это брал со своего старого проекта).
    Ответ написан
    Комментировать