2

I am implementing an own searchbar for Windows in WPF and I am curious if there is a possibility to override the single press of the Windows-Key with my own method (e.x. to show my own searchbar).

I am currently using the RegisterHotKey method as described in this answer https://stackoverflow.com/a/9330358/13215602, which works for key-combinations but it does not seem to work for a single windows key press.

        class HotKeyManager : IDisposable
        {
            private static Dictionary<int, HotKeyManager> _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 Action { get; private set; }
            public int Id { get; set; }

            // ******************************************************************
            public HotKeyManager(Key k, KeyModifier keyModifiers, Action 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, HotKeyManager>();
                    ComponentDispatcher.ThreadFilterMessage += new ThreadMessageEventHandler(ComponentDispatcherThreadFilterMessage);
                }

                _dictHotKeyToCalBackProc.Add(Id, this);

                Debug.Print(result.ToString() + ", " + Id + ", " + virtualKeyCode);
                return result;
            }

            // ******************************************************************
            public void Unregister()
            {
                if (_dictHotKeyToCalBackProc.ContainsKey(Id))
                {
                    _dictHotKeyToCalBackProc.Remove(Id);
                    UnregisterHotKey(IntPtr.Zero, Id);
                }
            }

            // ******************************************************************
            private static void ComponentDispatcherThreadFilterMessage(ref MSG msg, ref bool handled)
            {
                if (!handled)
                {
                    if (msg.message == WmHotKey)
                    {
                        HotKeyManager hotKey;

                        if (_dictHotKeyToCalBackProc.TryGetValue((int)msg.wParam, out hotKey))
                        {
                            if (hotKey.Action != null)
                            {
                                hotKey.Action.Invoke();
                            }
                            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
        }

        // ******************************************************************
    }
TheGoobsy
  • 75
  • 1
  • 6
  • 3
    _"but it does not seem to work for a single windows key press"_ - and it shouldn't. You would instantly disable all other hotkey combinations that are based on the windows-key. Not so great of an idea. – Fildor Aug 26 '20 at 12:10
  • Looking up the [Key Enum](https://learn.microsoft.com/en-us/dotnet/api/system.windows.input.key?redirectedfrom=MSDN&view=netcore-3.1), there are key codes for the single left and right WIN keys. But I have no idea if you can use them as a HotKey. – Martin Backasch Aug 26 '20 at 12:22
  • @Fildor wouldn't that be a problem only for catching every "keydown" of the Windows key, but not if you were acting on a full "keypress"? – StayOnTarget Aug 27 '20 at 12:03
  • 1
    Well, have a look at the above code. That's simply not how hot key registration works. You register Keys, that can be modified by Alt, Ctrl, Both, ... So, if I was to be able to register the WIN Key by itself then this could happen: I press WIN, wanting to press WIN+L to lock the screen. Then I realize, I have to still do something and instead of pressing L, I release the WIN key -> BAM hot key pressed. Did I want that? No. Did I have a way to avoid that? No. :( unhappy user. – Fildor Aug 27 '20 at 12:13
  • Thank you for your answers! @Fildor Unfortunately (for my goal) you are right. After a bit of reserach I also found `Keyboard shortcuts that involve the WINDOWS key are reserved for use by the operating system.` in the official Microsoft docs, which totally makes sense. But I do not fully agree on your opinion with the unhappy user in my use-case, because the hotkey should replace the default Windows-Search (Start-Menu), which would open anyway on an unintentionally press of the Windows Key. Now it would open my SearchBar, so I think this would not make any difference. – TheGoobsy Aug 27 '20 at 20:12

0 Answers0