A
A
Artem2020-07-17 20:04:07
C++ / C#
Artem, 2020-07-17 20:04:07

How to make keyboard keypress handler in inactive form?

The bottom line is this: you need to make sure that the program works in the background and catches the key combination at the right time, for example, ctrl + LMB.
I read that it can be implemented through hooks, but my knowledge is not very great in this direction, I would like to see a good example.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
N
NiceHack, 2020-07-19
@Timon1221

I want to clarify the essence of the issue, it turns out that your program works in window forms, and you want that when you press a certain key combination, it closes and works in the background, and vice versa also opens with a key combination. If so, then there is a ready-made class right in window forms, it is called KeyboardHook , you just connect it, insert it into the window forms initialization code , where you declare it and assign keys to it and it will work in the background and catch keyboard shortcuts, and for you need to connect a link to the user32.dll library (It is already built into Visual Studio and you do not need to download a third-party library ) and only then use it.I hope you know how to connect links to libraries. If not, then google it . By the way, I work mainly on WPF and you can’t connect this library to it (I don’t know why), only to window forms , and I have to insert it manually as a class (you can also not connect the whole library, but connect only one class, copy and paste it as your class). Here is an example of using this class:

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());

And here she is
// Единственное, я тут поменял все на слово 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
    }

I hope I understood your question correctly and could help you. And no practical knowledge is needed,
he told everything in great detail, if you ask questions ( Warning, there may be errors in the code because I took it from my old project ).

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question