One feature of the new Windows 7 SuperBar that I particularly like is the ability to pin applications. This creates a single button that can be used to both launch the application (when it isn't already running) or to activate it if the app was already active. What I like about this concept, is that it expresses the user's wish much better in this way: a button to run Word can now be used to just "give me Word, I don't care if it's already running".
Since I usually work more keyboard- than mouse-centric, I came up with a way to mimic this behavior in AutoHotkey. I wrote a script that offers the following functionality:
It took me a little time to work out the AutoHotkey script syntax, especially for dealing with arrays. In the script you set up an array of shortcut information, which serves as a settings registry. It contains the following parts:
Adding a entry goes like this:
;--1. SETUP ; enter label, name, groupname, windowId, runcommand AddShortcut("Windows Explorer", "Explorer", "ExplorerGroup", "ahk_class CabinetWClass", "C:\windows\explorer.exe /select,d:" )
The next step involves hooking up the shortcut keys. This is standard AutoHotkey suff, so please refer to the AHK manual for doing this. An example for Explorer and Firefox:
#E::MyNewActivate("Explorer") +#E::MyRun("Explorer") F19::MyNewActivate("FF") +F19::MyRun("FF")
So, Windows key + E does the launch-or-activate trick, whereas Shift + Win + E forces a new Explorer window.
The rest of the script adds some visual eye candy that is in no way functionally necessary, but it gives a nice, semi-transparent window that fades quickly. The three possible windows are shown at the top of this post.
The entire script is listed below; click expand source to view or copy.
#InstallKeybdHook ;--AUTOEXEC SECTION GroupArrayCount := 0 SetTitleMatchMode 2 ;--DISPLAY SETTINGS ; INITIAL_TRANSPARENCY := 150 DELTA_TRANSPARENCY := 25 INITIAL_DELAY := 400 DELTA_DELAY := 50 ;--1. SETUP ; enter label, name, groupname, windowId, runcommand ; AddShortcut("Windows Explorer", "Explorer", "ExplorerGroup", "ahk_class CabinetWClass", "C:\windows\explorer.exe /select,d:" ) AddShortcut("Outlook", "Outlook", "OutlookGroup", "ahk_class rctrl_renwnd32", "C:\Program Files (x86)\Microsoft Office\Office12\outlook.exe") AddShortcut("Firefox", "FF", "FireFoxGroup", "ahk_class MozillaUIWindowClass", "C:\Program Files (x86)\Mozilla Firefox\firefox.exe" ) AddShortcut("Calculator", "Calculator", "", "ahk_class CalcFrame", "c:\windows\system32\calc.exe") ;--2. ASSIGN KEYS ; win + E does a "run or activate", shift + win + E forces a new window #E::MyNewActivate("Explorer") +#E::MyRun("Explorer") F14::MyNewActivate("Outlook") F19::MyNewActivate("FF") +F19::MyRun("FF") ;--Ctrl + Shift + Esc starts Process Explorer (task manager on steroids) +^Escape::MyNewActivate("PE") #C::MyNewActivate("Calculator") ; ;--/AUTOEXEC SECTION ; FUNCTION SECTION GlobalTrans := INITIAL_TRANSPARENCY ;--CloseWin has to be an AHK subroutine, SetTimer doesn't work with functions ; also note: subroutines do not require the "global" keyword ; to manipulate global vars CloseWin: If (GlobalTrans <= 0) { Gui, Destroy } else { WinSet Transparent, %GlobalTrans%, ahk_class AutoHotkeyGUI GlobalTrans := GlobalTrans - DELTA_TRANSPARENCY ; negative time means run only once SetTimer, CloseWin, -%DELTA_DELAY% } return ShowText(text, textColor) { global GlobalTrans := INITIAL_TRANSPARENCY Gui, Destroy SetTimer, CloseWin, Off Gui +LastFound +AlwaysOnTop -Caption +ToolWindow Gui, Color, 404040 Gui, Font, s32 Gui, Add, Text, c%textColor%, %text% SetTimer, CloseWin, -%INITIAL_DELAY% Gui, Show, Center NoActivate WinSet Transparent, %GlobalTrans%, ahk_class AutoHotkeyGUI } AddShortcut(label, key, groupName, windowId, runCommand) { global GroupArrayCount += 1 Labels%GroupArrayCount% := label Keys%GroupArrayCount% := key if (groupName != "") { Groups%GroupArrayCount% := groupName } Ids%GroupArrayCount% := windowId Commands%GroupArrayCount% := runCommand if (groupName != "") { GroupAdd %groupName%,%windowId% } } MyNewActivate(key) { global Loop %GroupArrayCount% { if (key == Keys%A_Index%) { local thisId := Ids%A_Index% local label := Labels%A_Index% if WinExist(thisId) { ShowText("switching to " . label, "Lime") local thisGroup := Groups%A_Index% if (thisGroup == "") { WinActivate %thisId% } else { GroupActivate %thisGroup%,r } } else { ShowText("launching " . label, "FF8800") local thisCommand := Commands%A_Index% run, %thisCommand% } break ; terminate the lookup } } } MyRun(key) { global Loop %GroupArrayCount% { if (key == Keys%A_Index%) { local label := Labels%A_Index% ShowText("force new " . label, "FF3300") local thisCommand := Commands%A_Index% run, %thisCommand% break ; terminate the lookup } } }
Note that line 46 should read If (GlobalTrans <= 0), but the AHK brush for SyntaxHighlighter gets a bit confused here (since the semicolon ";" is also the AHK comment character). I found this brush here.
If (GlobalTrans <= 0)