{"id":902,"date":"2009-11-06T11:08:05","date_gmt":"2009-11-06T10:08:05","guid":{"rendered":"http:\/\/www.navision-blog.de\/2009\/11\/06\/observing-global-shortcuts\/"},"modified":"2009-11-06T11:12:51","modified_gmt":"2009-11-06T10:12:51","slug":"observing-global-shortcuts","status":"publish","type":"post","link":"http:\/\/www.navision-blog.de\/blog\/2009\/11\/06\/observing-global-shortcuts\/","title":{"rendered":"Observing global hotkeys in C# \/ F#"},"content":{"rendered":"<p>I recently had the problem to register a global hotkey, but my \u201cold\u201d Win32-API calls didn\u2019t work with WPF. I looked around the web and found the \u201c<a href=\"http:\/\/mwinapi.sourceforge.net\/\">Managed Windows API<\/a>\u201d, but I didn\u2019t want to add another external dependency to my project, so I extracted the core functions for registering hotkeys and condensed the code to a new version. <\/p>\n<p>As the original \u201cManaged Windows API\u201d is licensed by the GNU Lesser General Public License (LGPL) I want to provide my modifications here.<\/p>\n<p>First we need a Window which can dispatch the window messages to our event handlers:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> A Win32 native window that delegates window messages to <\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: green\">handlers. So several<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> components can use the same native window to save <\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: green\">&quot;USER resources&quot;. This class<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> is useful when writing your own components.<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;\/summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">public<\/span> <span style=\"color: blue\">sealed<\/span> <span style=\"color: blue\">class<\/span> <span style=\"color: #2b91af\">EventDispatchingNativeWindow<\/span> : <span style=\"color: #2b91af\">NativeWindow<\/span><\/p>\n<p style=\"margin: 0px\">{<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">static<\/span> <span style=\"color: blue\">readonly<\/span> <span style=\"color: #2b91af\">Object<\/span> MyLock = <span style=\"color: blue\">new<\/span> <span style=\"color: #2b91af\">Object<\/span>();<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">static<\/span> <span style=\"color: #2b91af\">EventDispatchingNativeWindow<\/span> _instance;<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> Create your own event dispatching window.<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;\/summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">public<\/span> EventDispatchingNativeWindow()<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; {<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; CreateHandle(<span style=\"color: blue\">new<\/span> <span style=\"color: #2b91af\">CreateParams<\/span>());<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; }<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> A global instance which can be used by components <\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: green\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span>that do not need<\/span><span style=\"color: green\"> their own window.<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;\/summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">public<\/span> <span style=\"color: blue\">static<\/span> <span style=\"color: #2b91af\">EventDispatchingNativeWindow<\/span> Instance<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; {<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">get<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">lock<\/span> (MyLock)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; {<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">return<\/span> <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; _instance ?? <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; (_instance = <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">new<\/span> <span style=\"color: #2b91af\">EventDispatchingNativeWindow<\/span>());<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; }<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> Attach your event handlers here.<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;\/summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">public<\/span> <span style=\"color: blue\">event<\/span> <span style=\"color: #2b91af\">WndProcEventHandler<\/span> EventHandler;<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> Parse messages passed to this window and send <\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: gray\">&#160;&#160;&#160; \/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: green\">them to the event handlers.<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;\/summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;param name=&quot;m&quot;&gt;<\/span><span style=\"color: green\">A System.Windows.Forms.Message <\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: gray\">&#160;&#160;&#160; \/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: green\">that is associated with the <\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> current Windows message.<\/span><span style=\"color: gray\">&lt;\/param&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">protected<\/span> <span style=\"color: blue\">override<\/span> <span style=\"color: blue\">void<\/span> WndProc(<span style=\"color: blue\">ref<\/span> <span style=\"color: #2b91af\">Message<\/span> m)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; {<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">bool<\/span> handled = <span style=\"color: blue\">false<\/span>;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">if<\/span> (EventHandler != <span style=\"color: blue\">null<\/span>)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; EventHandler(<span style=\"color: blue\">ref<\/span> m, <span style=\"color: blue\">ref<\/span> handled);<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">if<\/span> (!handled)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">base<\/span>.WndProc(<span style=\"color: blue\">ref<\/span> m);<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; }<\/p>\n<p style=\"margin: 0px\">}<\/p>\n<\/p><\/div>\n<p>Now we can write our global hotkey handler class:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> Specifies a class that creates a global keyboard hotkey.<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;\/summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">public<\/span> <span style=\"color: blue\">class<\/span> <span style=\"color: #2b91af\">GlobalHotkey<\/span><\/p>\n<p style=\"margin: 0px\">{<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">static<\/span> <span style=\"color: blue\">readonly<\/span> <span style=\"color: #2b91af\">Object<\/span> MyStaticLock = <span style=\"color: blue\">new<\/span> <span style=\"color: #2b91af\">Object<\/span>();<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">static<\/span> <span style=\"color: blue\">int<\/span> _hotkeyCounter = 0xA000;<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">readonly<\/span> <span style=\"color: blue\">int<\/span> _hotkeyIndex;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">readonly<\/span> <span style=\"color: #2b91af\">IntPtr<\/span> _hWnd;<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> Initializes a new instance of this class.<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;\/summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;param name=&quot;keys&quot;&gt;<\/span><span style=\"color: green\">The keys.<\/span><span style=\"color: gray\">&lt;\/param&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;param name=&quot;ctrl&quot;&gt;<\/span><span style=\"color: green\">if <\/span><span style=\"color: gray\">&lt;c&gt;<\/span><span style=\"color: green\">true<\/span><span style=\"color: gray\">&lt;\/c&gt;<\/span><span style=\"color: green\"> [CTRL].<\/span><span style=\"color: gray\">&lt;\/param&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;param name=&quot;alt&quot;&gt;<\/span><span style=\"color: green\">if <\/span><span style=\"color: gray\">&lt;c&gt;<\/span><span style=\"color: green\">true<\/span><span style=\"color: gray\">&lt;\/c&gt;<\/span><span style=\"color: green\"> [alt].<\/span><span style=\"color: gray\">&lt;\/param&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;param name=&quot;shift&quot;&gt;<\/span><span style=\"color: green\">if <\/span><span style=\"color: gray\">&lt;c&gt;<\/span><span style=\"color: green\">true<\/span><span style=\"color: gray\">&lt;\/c&gt;<\/span><span style=\"color: green\"> [shift].<\/span><span style=\"color: gray\">&lt;\/param&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;param name=&quot;winKey&quot;&gt;<\/span><span style=\"color: green\">if <\/span><span style=\"color: gray\">&lt;c&gt;<\/span><span style=\"color: green\">true<\/span><span style=\"color: gray\">&lt;\/c&gt;<\/span><span style=\"color: green\"> [win key].<\/span><span style=\"color: gray\">&lt;\/param&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">public<\/span> GlobalHotkey(<span style=\"color: #2b91af\">Keys<\/span> keys, <span style=\"color: blue\">bool<\/span> ctrl, <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">bool<\/span> alt, <span style=\"color: blue\">bool<\/span> shift, <span style=\"color: blue\">bool<\/span> winKey)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; {<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; KeyCode = keys;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; Ctrl = ctrl;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; Alt = alt;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; Shift = shift;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; WindowsKey = winKey;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: #2b91af\">EventDispatchingNativeWindow<\/span>.Instance.EventHandler <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; += NwEventHandler;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">lock<\/span> (MyStaticLock)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; {<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; _hotkeyIndex = ++_hotkeyCounter;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; }<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; _hWnd = <span style=\"color: #2b91af\">EventDispatchingNativeWindow<\/span>.Instance.Handle;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; Enable();<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; }<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> The key code of the hotkey.<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;\/summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">public<\/span> <span style=\"color: #2b91af\">Keys<\/span> KeyCode { <span style=\"color: blue\">get<\/span>; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">set<\/span>; }<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> Whether the shortcut includes the Control modifier.<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;\/summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">public<\/span> <span style=\"color: blue\">bool<\/span> Ctrl { <span style=\"color: blue\">get<\/span>; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">set<\/span>; }<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> Whether this shortcut includes the Alt modifier.<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;\/summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">public<\/span> <span style=\"color: blue\">bool<\/span> Alt { <span style=\"color: blue\">get<\/span>; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">set<\/span>; }<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> Whether this shortcut includes the shift modifier.<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;\/summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">public<\/span> <span style=\"color: blue\">bool<\/span> Shift { <span style=\"color: blue\">get<\/span>; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">set<\/span>; }<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> Whether this shortcut includes the Windows key modifier.<\/span><\/p>\n<p style=\"margin: 0px\">\n<p style=\"margin: 0px\"><span style=\"color: green\"><\/span><\/p>\n<p>&#160;&#160;&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;\/summary&gt;<\/span>    <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">public<\/span> <span style=\"color: blue\">bool<\/span> WindowsKey { <span style=\"color: blue\">get<\/span>; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">set<\/span>; }<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; ~GlobalHotkey()<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; {<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; Disable();<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: #2b91af\">EventDispatchingNativeWindow<\/span>.Instance.EventHandler <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; -= NwEventHandler;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; }<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> Enables the hotkey. When the hotkey is enabled, <\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: gray\">&#160;&#160;&#160; \/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: green\">pressing it causes a<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;c&gt;<\/span><span style=\"color: green\">HotkeyPressed<\/span><span style=\"color: gray\">&lt;\/c&gt;<\/span><span style=\"color: green\"> event instead of being <\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: gray\">&#160;&#160;&#160; \/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: green\">handled by the active<\/span><span style=\"color: green\"> application.<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;\/summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">void<\/span> Enable()<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; {<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: green\">\/\/ register hotkey<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">int<\/span> fsModifiers = 0;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">if<\/span> (Shift) fsModifiers += ModShift;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">if<\/span> (Ctrl) fsModifiers += ModControl;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">if<\/span> (Alt) fsModifiers += ModAlt;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">if<\/span> (WindowsKey) fsModifiers += ModWin;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">bool<\/span> success = <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; RegisterHotKey(_hWnd, _hotkeyIndex, <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; fsModifiers, (<span style=\"color: blue\">int<\/span>) KeyCode);<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">if<\/span> (!success)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">throw<\/span> <span style=\"color: blue\">new<\/span> <\/p>\n<p style=\"margin: 0px\"><span style=\"color: #2b91af\"><font color=\"#000000\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <\/font>Exception<\/span>(<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: #a31515\">&quot;Could not register hotkey (already in use).&quot;<\/span>);<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; }<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> Disables this instance.<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;\/summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">void<\/span> Disable()<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; {<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: green\">\/\/ unregister hotkey<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; UnregisterHotKey(_hWnd, _hotkeyIndex);<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; }<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> Occurs when the hotkey is pressed.<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: gray\">\/\/\/<\/span><span style=\"color: green\"> <\/span><span style=\"color: gray\">&lt;\/summary&gt;<\/span><\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">public<\/span> <span style=\"color: blue\">event<\/span> <span style=\"color: #2b91af\">EventHandler<\/span> HotkeyPressed;<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">void<\/span> NwEventHandler(<span style=\"color: blue\">ref<\/span> <span style=\"color: #2b91af\">Message<\/span> m, <span style=\"color: blue\">ref<\/span> <span style=\"color: blue\">bool<\/span> handled)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; {<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">if<\/span> (handled) <span style=\"color: blue\">return<\/span>;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">if<\/span> (m.Msg != WmHotkey || <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; m.WParam.ToInt32() != _hotkeyIndex)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">return<\/span>;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">if<\/span> (HotkeyPressed != <span style=\"color: blue\">null<\/span>)<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; HotkeyPressed(<span style=\"color: blue\">this<\/span>, <span style=\"color: #2b91af\">EventArgs<\/span>.Empty);<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160; handled = <span style=\"color: blue\">true<\/span>;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; }<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">&#160;&#160;&#160; #region<\/span> PInvoke Declarations<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">const<\/span> <span style=\"color: blue\">int<\/span> ModAlt = 0x0001;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">const<\/span> <span style=\"color: blue\">int<\/span> ModControl = 0x0002;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">const<\/span> <span style=\"color: blue\">int<\/span> ModShift = 0x0004;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">const<\/span> <span style=\"color: blue\">int<\/span> ModWin = 0x0008;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">const<\/span> <span style=\"color: blue\">int<\/span> WmHotkey = 0x0312;<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; [<span style=\"color: #2b91af\">DllImport<\/span>(<span style=\"color: #a31515\">&quot;user32.dll&quot;<\/span>, SetLastError = <span style=\"color: blue\">true<\/span>)]<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">static<\/span> <span style=\"color: blue\">extern<\/span> <span style=\"color: blue\">bool<\/span> RegisterHotKey(<span style=\"color: #2b91af\">IntPtr<\/span> hWnd, <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">int<\/span> id, <span style=\"color: blue\">int<\/span> fsModifiers, <span style=\"color: blue\">int<\/span> vlc);<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; [<span style=\"color: #2b91af\">DllImport<\/span>(<span style=\"color: #a31515\">&quot;user32.dll&quot;<\/span>, SetLastError = <span style=\"color: blue\">true<\/span>)]<\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; <span style=\"color: blue\">private<\/span> <span style=\"color: blue\">static<\/span> <span style=\"color: blue\">extern<\/span> <span style=\"color: blue\">bool<\/span> UnregisterHotKey(<span style=\"color: #2b91af\">IntPtr<\/span> hWnd, <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <span style=\"color: blue\">int<\/span> id);<\/p>\n<p style=\"margin: 0px\">&#160;<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">&#160;&#160;&#160; #endregion<\/span><\/p>\n<p style=\"margin: 0px\">}<\/p>\n<\/p><\/div>\n<p>Now we can easily register a global hotkey or use it as an observable in F#:<\/p>\n<div style=\"font-family: courier new; background: white; color: black; font-size: 10pt\">\n<p style=\"margin: 0px\"><span style=\"color: green\">\/\/\/ system-wide keyboard hook<\/span><\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> hotkey = <span style=\"color: blue\">new<\/span> GlobalHotkey(Keys.Q,<span style=\"color: blue\">true<\/span>,<span style=\"color: blue\">false<\/span>,<span style=\"color: blue\">false<\/span>,<span style=\"color: blue\">false<\/span>)<\/p>\n<p style=\"margin: 0px\"><span style=\"color: blue\">let<\/span> hookObserver =<\/p>\n<p style=\"margin: 0px\">&#160; hotkey.HotkeyPressed&#160; <\/p>\n<p style=\"margin: 0px\">&#160;&#160;&#160; |&gt; Observable.subscribe (<span style=\"color: blue\">fun<\/span> _ <span style=\"color: blue\">-&gt;<\/span> printfn <span style=\"color: maroon\">&quot;Hotkey pressed&quot;<\/span>)<\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>I recently had the problem to register a global hotkey, but my \u201cold\u201d Win32-API calls didn\u2019t work with WPF. I looked around the web and found the \u201cManaged Windows API\u201d, but I didn\u2019t want to add another external dependency to my project, so I extracted the core functions for registering hotkeys and condensed the code [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[12,448],"tags":[81,664,584,583,585],"_links":{"self":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/902"}],"collection":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/comments?post=902"}],"version-history":[{"count":2,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/902\/revisions"}],"predecessor-version":[{"id":904,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/posts\/902\/revisions\/904"}],"wp:attachment":[{"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/media?parent=902"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/categories?post=902"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.navision-blog.de\/blog\/wp-json\/wp\/v2\/tags?post=902"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}