<p>I'm building an application in C# using WPF. How can I bind to some keys?</p>

<p>Also, how can I bind to the <a href="http://en.wikipedia.org/wiki/Windows_key" rel="noreferrer">Windows key</a>?</p>

[{'answer_id': 48942, 'author': 'John Virgolino', 'author_id': 4246, 'author_profile': 'https://Stackoverflow.com/users/4246', 'pm_score': 1, 'selected': False, 'text': '<p>I\'m not sure about WPF, but this may help. I used the solution described in <em><a href="http://www.pinvoke.net/default.aspx/user32/RegisterHotKey.html" rel="nofollow noreferrer">RegisterHotKey (user32)</a></em> (modified to my needs of course) for a C# Windows Forms application to assign a CTRL-KEY combination within Windows to bring up a C# form, and it worked beautifully (even on Windows Vista). I hope it helps and good luck!</p>\n'}, {'answer_id': 49102, 'author': 'Andy', 'author_id': 3857, 'author_profile': 'https://Stackoverflow.com/users/3857', 'pm_score': 0, 'selected': False, 'text': "<p><code>RegisterHotKey()</code> suggested by John could work - the only catch is that it requires an HWND (using <code>PresentationSource.FromVisual()</code>, and casting the result to an HwndSource). </p>\n\n<p>However, you'll also need to respond to the <code>WM_HOTKEY</code> message - I'm not sure if there is a way to get access to the WndProc of a WPF window or not (which can be done for Windows Forms windows).</p>\n"}, {'answer_id': 49171, 'author': 'Gishu', 'author_id': 1695, 'author_profile': 'https://Stackoverflow.com/users/1695', 'pm_score': 6, 'selected': True, 'text': '<p>I\'m not sure of what you mean by &quot;global&quot; here, but here it goes (I\'m assuming you mean a command at the application level, for example, <em>Save All</em> that can be triggered from anywhere by <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>S</kbd>.)</p>\n<p>You find the global <code>UIElement</code> of your choice, for example, the top level window which is the parent of all the controls where you need this binding. Due to &quot;bubbling&quot; of WPF events, events at child elements will bubble all the way up to the root of the control tree.</p>\n<p>Now, first you need</p>\n<ol>\n<li>to bind the Key-Combo with a Command using an <code>InputBinding</code> like this</li>\n<li>you can then hookup the command to your handler (e.g. code that gets called by <code>SaveAll</code>) via a <code>CommandBinding</code>.</li>\n</ol>\n<p>For the <kbd>Windows</kbd> Key, you use the right <a href="http://msdn.microsoft.com/en-us/library/system.windows.input.key.aspx" rel="nofollow noreferrer">Key</a> enumerated member, <strong><code>Key.LWin</code></strong> or <strong><code>Key.RWin</code></strong></p>\n<pre><code>public WindowMain()\n{\n   InitializeComponent();\n\n   // Bind Key\n   var ib = new InputBinding(\n       MyAppCommands.SaveAll,\n       new KeyGesture(Key.S, ModifierKeys.Shift | ModifierKeys.Control));\n   this.InputBindings.Add(ib);\n\n   // Bind handler\n   var cb = new CommandBinding( MyAppCommands.SaveAll);\n   cb.Executed += new ExecutedRoutedEventHandler( HandlerThatSavesEverthing );\n\n   this.CommandBindings.Add (cb );\n}\n\nprivate void HandlerThatSavesEverthing (object obSender, ExecutedRoutedEventArgs e)\n{\n  // Do the Save All thing here.\n}\n</code></pre>\n'}, {'answer_id': 1960122, 'author': 'jgraves', 'author_id': 204961, 'author_profile': 'https://Stackoverflow.com/users/204961', 'pm_score': 4, 'selected': False, 'text': '<p>If you\'re going to mix Win32 and WPF, here\'s how I did it:</p>\n\n<pre><code>using System;\nusing System.Runtime.InteropServices;\nusing System.Windows.Interop;\nusing System.Windows.Media;\nusing System.Threading;\nusing System.Windows;\nusing System.Windows.Input;\n\nnamespace GlobalKeyboardHook\n{\n    public class KeyboardHandler : IDisposable\n    {\n\n        public const int WM_HOTKEY = 0x0312;\n        public const int VIRTUALKEYCODE_FOR_CAPS_LOCK = 0x14;\n\n        [DllImport("user32.dll")]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);\n\n        [DllImport("user32.dll")]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        public static extern bool UnregisterHotKey(IntPtr hWnd, int id);\n\n        private readonly Window _mainWindow;\n        WindowInteropHelper _host;\n\n        public KeyboardHandler(Window mainWindow)\n        {\n            _mainWindow = mainWindow;\n            _host = new WindowInteropHelper(_mainWindow);\n\n            SetupHotKey(_host.Handle);\n            ComponentDispatcher.ThreadPreprocessMessage += ComponentDispatcher_ThreadPreprocessMessage;\n        }\n\n        void ComponentDispatcher_ThreadPreprocessMessage(ref MSG msg, ref bool handled)\n        {\n            if (msg.message == WM_HOTKEY)\n            {\n                //Handle hot key kere\n            }\n        }\n\n        private void SetupHotKey(IntPtr handle)\n        {\n            RegisterHotKey(handle, GetType().GetHashCode(), 0, VIRTUALKEYCODE_FOR_CAPS_LOCK);\n        }\n\n        public void Dispose()\n        {\n            UnregisterHotKey(_host.Handle, GetType().GetHashCode());\n        }\n    }\n}\n</code></pre>\n\n<p>You can get the virtual-key code for the hotkey you want to register here: <a href="http://msdn.microsoft.com/en-us/library/ms927178.aspx" rel="noreferrer">http://msdn.microsoft.com/en-us/library/ms927178.aspx</a></p>\n\n<p>There may be a better way, but this is what I\'ve got so far.</p>\n\n<p>Cheers!</p>\n'}, {'answer_id': 2643355, 'author': 'Mattias Wikström', 'author_id': 317213, 'author_profile': 'https://Stackoverflow.com/users/317213', 'pm_score': 1, 'selected': False, 'text': '<p>Although RegisterHotKey is sometimes precisely what you want, in most cases you probably do not want to use system-wide hotkeys. I ended up using code like the following:</p>\n<pre class="lang-cs prettyprint-override"><code>using System.Windows;\nusing System.Windows.Interop;\n\nnamespace WpfApp\n{\n    public partial class MainWindow : Window\n    {\n        const int WM_KEYUP = 0x0101;\n\n        const int VK_RETURN = 0x0D;\n        const int VK_LEFT = 0x25;  \n      \n        public MainWindow()\n        {\n            this.InitializeComponent();\n\n            ComponentDispatcher.ThreadPreprocessMessage += \n                ComponentDispatcher_ThreadPreprocessMessage;\n        }\n\n        void ComponentDispatcher_ThreadPreprocessMessage(\n            ref MSG msg, ref bool handled)\n        {\n            if (msg.message == WM_KEYUP)\n            {\n                if ((int)msg.wParam == VK_RETURN)\n                    MessageBox.Show(&quot;RETURN was pressed&quot;);\n                \n                if ((int)msg.wParam == VK_LEFT)\n                    MessageBox.Show(&quot;LEFT was pressed&quot;);\n            }\n        }\n    }\n}\n</code></pre>\n'}, {'answer_id': 9330358, 'author': 'Eric Ouellet', 'author_id': 452845, 'author_profile': 'https://Stackoverflow.com/users/452845', 'pm_score': 6, 'selected': False, 'text': '<p>This is a full working solution, hope it helps...</p>\n\n<p>Usage:</p>\n\n<pre><code>_hotKey = new HotKey(Key.F9, KeyModifier.Shift | KeyModifier.Win, OnHotKeyHandler);\n</code></pre>\n\n<p>...</p>\n\n<pre><code>private void OnHotKeyHandler(HotKey hotKey)\n{\n    SystemHelper.SetScreenSaverRunning();\n}\n</code></pre>\n\n<p>Class:</p>\n\n<pre><code>using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Linq;\nusing System.Net.Mime;\nusing System.Runtime.InteropServices;\nusing System.Text;\nusing System.Windows;\nusing System.Windows.Input;\nusing System.Windows.Interop;\n\nnamespace UnManaged\n{\n    public class HotKey : IDisposable\n    {\n        private static Dictionary&lt;int, HotKey&gt; _dictHotKeyToCalBackProc;\n\n        [DllImport("user32.dll")]\n        private static extern bool RegisterHotKey(IntPtr hWnd, int id, UInt32 fsModifiers, UInt32 vlc);\n\n        [DllImport("user32.dll")]\n        private static extern bool UnregisterHotKey(IntPtr hWnd, int id);\n\n        public const int WmHotKey = 0x0312;\n\n        private bool _disposed = false;\n\n        public Key Key { get; private set; }\n        public KeyModifier KeyModifiers { get; private set; }\n        public Action&lt;HotKey&gt; Action { get; private set; }\n        public int Id { get; set; }\n\n        // ******************************************************************\n        public HotKey(Key k, KeyModifier keyModifiers, Action&lt;HotKey&gt; action, bool register = true)\n        {\n            Key = k;\n            KeyModifiers = keyModifiers;\n            Action = action;\n            if (register)\n            {\n                Register();\n            }\n        }\n\n        // ******************************************************************\n        public bool Register()\n        {\n            int virtualKeyCode = KeyInterop.VirtualKeyFromKey(Key);\n            Id = virtualKeyCode + ((int)KeyModifiers * 0x10000);\n            bool result = RegisterHotKey(IntPtr.Zero, Id, (UInt32)KeyModifiers, (UInt32)virtualKeyCode);\n\n            if (_dictHotKeyToCalBackProc == null)\n            {\n                _dictHotKeyToCalBackProc = new Dictionary&lt;int, HotKey&gt;();\n                ComponentDispatcher.ThreadFilterMessage += new ThreadMessageEventHandler(ComponentDispatcherThreadFilterMessage);\n            }\n\n            _dictHotKeyToCalBackProc.Add(Id, this);\n\n            Debug.Print(result.ToString() + ", " + Id + ", " + virtualKeyCode);\n            return result;\n        }\n\n        // ******************************************************************\n        public void Unregister()\n        {\n            HotKey hotKey;\n            if (_dictHotKeyToCalBackProc.TryGetValue(Id, out hotKey))\n            {\n                UnregisterHotKey(IntPtr.Zero, Id);\n            }\n        }\n\n        // ******************************************************************\n        private static void ComponentDispatcherThreadFilterMessage(ref MSG msg, ref bool handled)\n        {\n            if (!handled)\n            {\n                if (msg.message == WmHotKey)\n                {\n                    HotKey hotKey;\n\n                    if (_dictHotKeyToCalBackProc.TryGetValue((int)msg.wParam, out hotKey))\n                    {\n                        if (hotKey.Action != null)\n                        {\n                            hotKey.Action.Invoke(hotKey);\n                        }\n                        handled = true;\n                    }\n                }\n            }\n        }\n\n        // ******************************************************************\n        // Implement IDisposable.\n        // Do not make this method virtual.\n        // A derived class should not be able to override this method.\n        public void Dispose()\n        {\n            Dispose(true);\n            // This object will be cleaned up by the Dispose method.\n            // Therefore, you should call GC.SupressFinalize to\n            // take this object off the finalization queue\n            // and prevent finalization code for this object\n            // from executing a second time.\n            GC.SuppressFinalize(this);\n        }\n\n        // ******************************************************************\n        // Dispose(bool disposing) executes in two distinct scenarios.\n        // If disposing equals true, the method has been called directly\n        // or indirectly by a user\'s code. Managed and unmanaged resources\n        // can be _disposed.\n        // If disposing equals false, the method has been called by the\n        // runtime from inside the finalizer and you should not reference\n        // other objects. Only unmanaged resources can be _disposed.\n        protected virtual void Dispose(bool disposing)\n        {\n            // Check to see if Dispose has already been called.\n            if (!this._disposed)\n            {\n                // If disposing equals true, dispose all managed\n                // and unmanaged resources.\n                if (disposing)\n                {\n                    // Dispose managed resources.\n                    Unregister();\n                }\n\n                // Note disposing has been done.\n                _disposed = true;\n            }\n        }\n    }\n\n    // ******************************************************************\n    [Flags]\n    public enum KeyModifier\n    {\n        None = 0x0000,\n        Alt = 0x0001,\n        Ctrl = 0x0002,\n        NoRepeat = 0x4000,\n        Shift = 0x0004,\n        Win = 0x0008\n    }\n\n    // ******************************************************************\n}\n</code></pre>\n'}, {'answer_id': 11032209, 'author': 'Gorgsenegger', 'author_id': 412036, 'author_profile': 'https://Stackoverflow.com/users/412036', 'pm_score': 1, 'selected': False, 'text': '<p>I\'ve found the <a href="http://www.codeproject.com/Tips/274003/Global-Hotkeys-in-WPF#" rel="nofollow">Global Hotkeys in WPF</a> project on codeproject.com which does the job for me. It\'s relatively recent, does not need a reference to System.Windows.Forms and works "globally" in terms of reacting to the hotkey being pressed even if "your" application is not the active window.</p>\n'}, {'answer_id': 12676910, 'author': 'Louis Kottmann', 'author_id': 677014, 'author_profile': 'https://Stackoverflow.com/users/677014', 'pm_score': 4, 'selected': False, 'text': "<p>Registering OS level shortcuts is hardly ever a good thing: users don't want you to mess with their OS.<br></p>\n\n<p>That said, there is a much simpler and user friendly way of doing this in WPF, if you're ok with the hotkey working within the application only (i.e as long as your WPF app has the focus):</p>\n\n<p>In App.xaml.cs :</p>\n\n<pre><code>protected override void OnStartup(StartupEventArgs e)\n{\n   EventManager.RegisterClassHandler(typeof(Window), Window.PreviewKeyUpEvent, new KeyEventHandler(OnWindowKeyUp));\n}\n\nprivate void OnWindowKeyUp(object source, KeyEventArgs e))\n{\n   //Do whatever you like with e.Key and Keyboard.Modifiers\n}\n</code></pre>\n\n<p>It's that simple</p>\n"}, {'answer_id': 15646002, 'author': 'Mario', 'author_id': 1357191, 'author_profile': 'https://Stackoverflow.com/users/1357191', 'pm_score': 1, 'selected': False, 'text': "<p>Baboon's solution works best because you may have multiple windows. I did tweak it so it uses the PreviewKeyDownEvent instead of the PreviewKeyUpEvent in order to handle repetition in keystrokes.</p>\n\n<p>I would advise against OS-level registration unless you are writing something like a snipping tool or an audio recording app as it will let you access functionality when the window is not focused.</p>\n"}, {'answer_id': 33797344, 'author': 'BornToCode', 'author_id': 1057791, 'author_profile': 'https://Stackoverflow.com/users/1057791', 'pm_score': 2, 'selected': False, 'text': '<p>This is similar to the answers already given, but I find it a bit cleaner:</p>\n\n<pre><code>using System;\nusing System.Windows.Forms;\n\nnamespace GlobalHotkeyExampleForm\n{\n    public partial class ExampleForm : Form\n    {\n        [System.Runtime.InteropServices.DllImport("user32.dll")]\n        private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);\n        [System.Runtime.InteropServices.DllImport("user32.dll")]\n        private static extern bool UnregisterHotKey(IntPtr hWnd, int id);\n\n        enum KeyModifier\n        {\n            None = 0,\n            Alt = 1,\n            Control = 2,\n            Shift = 4,\n            WinKey = 8\n        }\n\n        public ExampleForm()\n        {\n            InitializeComponent();\n\n            int id = 0;     // The id of the hotkey. \n            RegisterHotKey(this.Handle, id, (int)KeyModifier.Shift, Keys.A.GetHashCode());       // Register Shift + A as global hotkey. \n        }\n\n        protected override void WndProc(ref Message m)\n        {\n            base.WndProc(ref m);\n\n            if (m.Msg == 0x0312)\n            {\n                /* Note that the three lines below are not needed if you only want to register one hotkey.\n                 * The below lines are useful in case you want to register multiple keys, which you can use a switch with the id as argument, or if you want to know which key/modifier was pressed for some particular reason. */\n\n                Keys key = (Keys)(((int)m.LParam &gt;&gt; 16) &amp; 0xFFFF);                  // The key of the hotkey that was pressed.\n                KeyModifier modifier = (KeyModifier)((int)m.LParam &amp; 0xFFFF);       // The modifier of the hotkey that was pressed.\n                int id = m.WParam.ToInt32();                                        // The id of the hotkey that was pressed.\n\n\n                MessageBox.Show("Hotkey has been pressed!");\n                // do something\n            }\n        }\n\n        private void ExampleForm_FormClosing(object sender, FormClosingEventArgs e)\n        {\n            UnregisterHotKey(this.Handle, 0);       // Unregister hotkey with id 0 before closing the form. You might want to call this more than once with different id values if you are planning to register more than one hotkey.\n        }\n    }\n}\n</code></pre>\n\n<p>I\'ve found it on <a href="http://www.fluxbytes.com/csharp/how-to-register-a-global-hotkey-for-your-application-in-c/" rel="nofollow">fluxbytes.com</a>.</p>\n'}, {'answer_id': 63843177, 'author': 'Anthony Nguyen', 'author_id': 12848112, 'author_profile': 'https://Stackoverflow.com/users/12848112', 'pm_score': 2, 'selected': False, 'text': '<p>With the NHotKey package, you can make your hotkey global:</p>\n<ul>\n<li><a href="https://github.com/thomaslevesque/NHotkey" rel="nofollow noreferrer">https://github.com/thomaslevesque/NHotkey</a></li>\n<li><a href="https://thomaslevesque.com/2014/02/05/wpf-declare-global-hotkeys-in-xaml-with-nhotkey/" rel="nofollow noreferrer">https://thomaslevesque.com/2014/02/05/wpf-declare-global-hotkeys-in-xaml-with-nhotkey/</a> (use web.archive.org if the link is broken)</li>\n</ul>\n<p>In short, for XAML, all you need to do is to replace</p>\n<pre><code>&lt;KeyBinding Gesture=&quot;Ctrl+Alt+Add&quot; Command=&quot;{Binding IncrementCommand}&quot; /&gt;\n</code></pre>\n<p>by</p>\n<pre><code>&lt;KeyBinding Gesture=&quot;Ctrl+Alt+Add&quot; Command=&quot;{Binding IncrementCommand}&quot;\n            HotkeyManager.RegisterGlobalHotkey=&quot;True&quot; /&gt;\n</code></pre>\n'}]
['https://Stackoverflow.com/questions/48935', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/146637/']