5

QUESTION

How does one programmatically interrogate Win7 to get a list of all currently active global keyboard shortcuts?

Scenario

In many versions of Windows there is the so called "Windows Key", a.k.a. "flag", "start key", et cetera.

Microsoft has a support article "Keyboard shortcuts for Windows" that lists many of these under the section "Microsoft Natural Keyboard keys", as well as many others the do not involve using the "Windows Key" such as the global Ctrl+C, et cetera.

Other keyboard shortcuts can be discovered by accident. For example, Windows Key + Left arrow or Right arrow in Win7 moves the focused window around the display, and, with multiple monitors, from one display to the next.

Still other keyboard shortcuts can be found in the "options" settings, for example, Left-Ctrl+Alt+K is the default for "Show KeePass Window".

Additionally, there may be hardware specific keyboard shortcuts, for example, on my laptop, Fn+F8 toggles speaker muting.

Stolen Keyboard Shortcuts

When Snagit is running, I've configured PrtSc as my shortcut, but when Visual Studio(VS) is running, it steals PrtSc from Snagit.

Two time consuming methods of manually discovered keyboard shortcuts

(a) Global keyboard shortcuts can be discovered by having only the desktop and a couple of windows open and trying various key combinations.

(b) in VS, many VS keyboard shortcuts can be discovered by trying various combinations in the keyboard shortcuts window where, if a combination is already used, VS will notify one about the current usage for that combination.

Two reasons for wanting to discover all currently active global keyboard shortcuts

(a) to avoid annoying accidents like Windows Logo Key+L which locks the computer.

(b) to determine which keys are currently still available for assignment.

Brad Rem
  • 6,036
  • 2
  • 25
  • 50
gerryLowry
  • 2,626
  • 5
  • 35
  • 44
  • basically this is hard since there are several ways of implementing "global hotkeys"... you can even use some weird technique to implement conditionally active global hotkeys which are not discoverable programatically for example... – Yahia Sep 09 '12 at 15:51
  • 1
    hehe, linking to "The Windows Key" might not be necessary in a *programming* community like StackOverflow. ;) – Patrick Sep 09 '12 at 16:23
  • @ Patrick: good point ... i tend to think about novices and people whose first language is not English ... you're right, i'm guessing most programmers would realize that, even most beginners. B-) – gerryLowry Sep 09 '12 at 17:49
  • @ Brad Rem ... thnx for the edit ... you've taught me at least two ways to make cleaner posts. much appreciated! – gerryLowry Sep 09 '12 at 17:57
  • @ Yahia ... thank you for your comment ... via Google **"conditionally active global hotkeys"**, i've discovered a number of interestinbg links to investigate, including [AutoHotkey](http://www.autohotkey.com/) which is c++ open source available at [githup](https://github.com/AutoHotkey/AutoHotkey/tree/master/Source). – gerryLowry Sep 10 '12 at 03:59
  • ideally i'd prefer to do this in c# .NET 4.5 but i'm not sure whether this is possible with c# managed code. – gerryLowry Sep 10 '12 at 04:02
  • 1
    @gerryLowry: If I understand your question, AutoHotkey is not really what you're looking for. You are looking for a program that discovers all the shortcuts currently assigned on the system? Example of such programs are [ActiveHotKeys](http://www.tranglos.com/download/activehotkeysportable.zip) and [HotKey explorer](http://hkcmdr.anymania.com/hkexplr_inst.exe). Also I'm curious as to your comment on my answer. – Chibueze Opata Sep 10 '12 at 10:27
  • @ Chibueze Opata: (a) yes, you do understand me correctly ... the reason that i find [AutoHotkey](http://www.autohotkey.com/) interesting is because it is [open source](http://github.com/AutoHotkey/AutoHotkey/zipball/master) and i'm hoping to get some ideas from the **AutoHotKey** source code. – gerryLowry Sep 10 '12 at 14:47
  • @ Chibueze Opata: (b) thank you for your answer, i've not commented on it yet because i've not had enough time to analyze it in depth; also, my weak understanding of programming system-wide hot keys has led me to *assume* that the system registry is involved, yet (1) your code example appears to be iterating "*.lnk*" files and (2) your code example requires a third party library from *codeproject* (not a bad thing, however, i wish to explore .NET Framework options as a first choice). – gerryLowry Sep 10 '12 at 14:48
  • update: while experimenting with [AutoHotKey](http://www.autohotkey.com/) i discovered it does not check whether a system-wide hotkey exists, for example, i accidentally overrode winLogo+x which on my laptop launches the *Windows Mobility Centre* applet; the AutoHotKey c++ [source code](http://github.com/AutoHotkey/AutoHotkey) from **github** compiles *almost* clean in vs2012 but is a substantial amount of code to examine. – gerryLowry Sep 11 '12 at 18:50
  • footnote: more hotkeys are here: [vista](http://windows.microsoft.com/en-CA/windows-vista/Keyboard-shortcuts) and [WinKey](http://www.microsoft.com/canada/smallbiz/themes/technology-basics/work-faster-with-winkey-shortcuts.mspx). – gerryLowry Sep 11 '12 at 18:52

1 Answers1

2

This is a quite interesting but difficult issue. The Windows Operating System apparently does not offer a direct way to do this via maybe EnumerateHotKeys? However, when the RegisterHotKey function is called, there's a search using __FindHotKey. So it may be possible to hack into this function and find out available hot keys. See this C example. There's also a complete example in assembly languagedownloadable from here but this is likely not to work in Windows Vista +.

Another method is to scan all the shortcuts in the system. This can really take a long time if you want to scan all shortcuts on the system. However you can still grab most of them using the common shortcut directories such as:

%AllUsersProfile%\desktop %UserProfile%\Start Menu %AllUsersProfile%\Start Menu %appdata%\Microsoft\Internet Explorer\Quick Launch %appdata%\Microsoft\Internet Explorer\Quick Launch\User Pinned\StartMenu %appdata%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar

Here's a simple program I just wrote that scans all the shortcuts in the UserProfile directory.

using IWshRuntimeLibrary;//You can download this library from http://www.codeproject.com/KB/dotnet/ShellLink/ShellLink.zip


WshShell wsh = new WshShellClass();
var files = GetFiles(Environment.ExpandEnvironmentVariables("%userprofile%"), "*.lnk*");
foreach (string f in files)
{
    try
    {
        WshShortcut wa = wsh.CreateShortcut(f) as WshShortcut;
        if (wa.Hotkey != "")
        {
            MessageBox.Show("Shortcut Found! - " + wa.Hotkey, wa.TargetPath);
        }
    }
    catch
    {
        continue;
    }
}

Grap the GetFiles method from here if you want to use it. The major advantage of the method is just to avoid directory permission issues.

Good luck.

Community
  • 1
  • 1
Chibueze Opata
  • 9,856
  • 7
  • 42
  • 65