0

I know there are a lot of resources already on how to capture a global hotkey with C# (using Ctrl, Alt, or whatever else), but I haven't seen any that work with the Windows key.

Is it possible to have a program capture and respond to a Win+* global keyboard shortcut? For example, show a form if the user presses Win+Z or something like that.

qJake
  • 16,821
  • 17
  • 83
  • 135
  • 1
    Do **not** create hotkeys with the Windows key. It is reserved for operating system functionality, your program will interfere with that and greatly inconvenience the user. – Hans Passant Nov 19 '13 at 22:17
  • It's not for any other user besides myself (I'm writing a helper program to save myself some time), and I know which Win+* shortcuts are used and which are not, so there won't be a collision. Feel better warning me about it, though? :P – qJake Nov 19 '13 at 22:25
  • Also, @HansPassant, you can't register a global hotkey that's already registered by the system, Windows will return this error: "Code: 1409, Error: Hot key is already registered". Seems perfectly safe and won't interfere with anything. – qJake Nov 20 '13 at 17:11

2 Answers2

1

The Windows keys can be used as any other modifier (const int MOD_WIN = 0x0008 according to MSDN). I have tested this with a RegisterHotKey-based code and works fine.

UPDATE

Sample code showing how to hook different combinations of keys including the Windows keys by relying on RegisterHotKey (LParam values collected manually):

[System.Runtime.InteropServices.DllImport("User32")] public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
[System.Runtime.InteropServices.DllImport("User32")] public static extern bool UnregisterHotKey(IntPtr hWnd, int id);

public const int MOD_SHIFT = 0x4;
public const int MOD_CONTROL = 0x2;
public const int MOD_ALT = 0x1;
public const int WM_HOTKEY = 0x312;
public const int MOD_WIN = 0x0008;

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_HOTKEY && m.WParam == (IntPtr)0)
    {
        IntPtr lParamWINZ = (IntPtr)5898248;
        IntPtr lParamWINCTRLA = (IntPtr)4259850;
        if (m.LParam == lParamWINZ)
        {
            MessageBox.Show("WIN+Z was pressed");
        }
        else if (m.LParam == lParamWINCTRLA)
        {
            MessageBox.Show("WIN+CTRL+A was pressed");
        }
    }
    base.WndProc(ref m);
}

private void Form1_Load(object sender, EventArgs e)
{
    this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);

    RegisterHotKey(this.Handle, 0, MOD_WIN, (int)Keys.Z);
    RegisterHotKey(this.Handle, 0, MOD_WIN + MOD_CONTROL, (int)Keys.A);
}

private void Form1_FormClosing(Object sender, FormClosingEventArgs e)
{
    UnregisterHotKey(this.Handle, 0);
}
varocarbas
  • 12,354
  • 4
  • 26
  • 37
  • So even though that documentation says **Keyboard shortcuts that involve the WINDOWS key are reserved for use by the operating system.**, they still work if you handle them? – qJake Nov 19 '13 at 21:36
  • @SpikeX Exactly this is what I have said. Shall I include a sample code? – varocarbas Nov 19 '13 at 21:37
  • You can include sample code if you wish for other people (e.g. people coming from Google), but I know how to check for this in C#. I'll accept once I can confirm it works. – qJake Nov 19 '13 at 22:34
  • @SpikeX No problem. I might add a sample code in a while right before leaving. – varocarbas Nov 19 '13 at 22:36
  • I tried registering the hotkey with the Win key modifier `0x08`, but Windows is returning error 1008: "An attempt was made to reference a token that does not exist". Any ideas? – qJake Nov 20 '13 at 17:01
  • @SpikeX I don't know what to say. I have only tried the implementation above and works fine (0x08 or 0x0008 does not matter). Why don't you try this code? Or post the code you tried and I can take a look at it. – varocarbas Nov 20 '13 at 17:03
  • Even weirder, it's still failing, but now there isn't an error code, it just returns code 0 which translates to "The operation completed successfully". – qJake Nov 20 '13 at 17:05
  • I'm using this implementation, it seemed to be a popular choice on SO: http://stackoverflow.com/questions/2450373/set-global-hotkeys-using-c-sharp – qJake Nov 20 '13 at 17:05
  • Oh, sorry, that wasn't the right error, this is (I'm trying to register Win+Z): Code: 1409, Error: Hot key is already registered – qJake Nov 20 '13 at 17:08
  • @SpikeX A bit big. See... I have used codes like the one above (in both VB.NET and C#) tons of times and it delivers an excellent performance (and, in this context, works perfectly), why don't you try it? The code you are referring it pretty big and the basic functionalities are the ones in the code I posted; it might be the case that what your code includes are in-the-safest-side bits which avoid the Win key to be used... – varocarbas Nov 20 '13 at 17:09
  • Oh, I found my problem, Win+Z is actually registered by Windows for something, even though it doesn't actually do anything. I found another Win+* combination that worked though, so in the end it is possible. Thanks for your help. :) – qJake Nov 20 '13 at 17:10
  • @SpikeX You are welcome. (But you can register Win+Z with the code I posted; at least, on my computer, running on Windows 7). – varocarbas Nov 20 '13 at 17:11
0

Even though the above solution seems to work for some people. It did not work for me. The only way to get the WIN key working was by disabling it in the registry.

https://msdn.microsoft.com/en-us/library/bb521407(v=winembedded.51).aspx

The downside: all WIN hotkeys are disabled.

There are two possible ways on doing this in the Registry:

(1) Systemwide: (I have not tested this one) HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ Keyboard Layout, Name: "Scancode Map", Type: REG_BINARY (Binary Value), Value Data: "00 00 00 00 00 00 00 00 03 00 00 00 00 00 5B E0 00 00 5C E0 00 00 00 00"

(2) For each user: (This is what I used) HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer, Name: "NoWinKeys", Data Type: REG_DWORD (DWORD Value), Value Data: 0 to disable restriction, or 1 to enable restriction

noherr
  • 11
  • 2
  • Windows 10 has been adding new shortcut keys and if one is reserved by the OS then you will not be able to use it (even if it doesn't appear to do anything, it may still be reserved). You'll need to find a key that is not reserved (the only one I know of right now is `N` but there may be one or two more). – qJake Feb 12 '18 at 15:15
  • Unfortunately WIN + N is occupied by "Send to OneNote" utility (Office 2013 and probably all newer versions). A complete list of all shortcuts can be found here https://support.microsoft.com/en-my/help/12445/windows-keyboard-shortcuts. Which means that ALL letters and numbers are reserved. After going through the list I only found the keys F2 and onward available. – noherr Feb 14 '18 at 05:21
  • Win+N becomes available if you close "Send to OneNote" and disable it from starting up on your computer. Of course, this doesn't work if you are deploying an application - my original question was regarding an application that I was writing for myself, not deploying anywhere. It still stands that you "shouldn't" write an app that uses a Win+_ hotkey because it breaks best practices, but if the app is just for yourself, it will work. – qJake Feb 14 '18 at 14:21