Skip to content

Instantly share code, notes, and snippets.

@akaleeroy
Last active April 16, 2025 16:26
Show Gist options
  • Save akaleeroy/f23bd4dd2ddae63ece2582ede842b028 to your computer and use it in GitHub Desktop.
Save akaleeroy/f23bd4dd2ddae63ece2582ede842b028 to your computer and use it in GitHub Desktop.
Easy Access to Currently Opened Folders

Easy Access to Currently Opened Folders

Windows Enhancement Productivity AutoHotkey v2

Enhance Open... or Save As... dialogs with a quick way to navigate to currently opened folders.

Easy Access to Currently Opened Folders v2 - Demo

This is an AutoHotkey v2 script that gives common file selection dialogs an extra feature: middle-clicking invokes a menu of currently opened folders. Say you want to save or upload something to/from a folder you've got open in Windows Explorer. The dialog box pops up with the last folder (from another project) or My Documents, and now you have to manually navigate to the folder you want, or copy-paste its path from the open Explorer window. I wanted to get to the active locations quicker. Recent Items wasn't exactly helping, so I made this by forking FavoriteFolders.ahk by Savage. Tested on Windows 7, 8, 10.

How it works

You run the script in the background the whole time Windows is on. I included it into another script with more helper functions and compiled it to an executable which is set to start with Windows.

  1. When one of these file selection dialogs pops up, Middle Click inside it. Or hit Ctrl + G. These are configurable at the top of the script.

  2. A menu appears with your current working directories.

  3. Select one and the script will quickly insert it in the dialog's address bar and take you there.

  4. Save or select your file.

Limitations

Special places like Computer, Libraries, Search results etc. won't show up in the menu. If you have the Desktop or User Profile folders opened in the taskbar they will show up twice.

#Requires AutoHotkey v2.0.3+
; # Goto openened folders
; A better "Recent Places"
#HotIf ShouldDisplayMenu()
~MButton::DisplayMenu()
; Ctrl + G like Listary
^g::DisplayMenu()
#HotIf
; "Namespaced" global variables
global GTOF := {
WinId : 0, ; Window ID under the mouse
Class : "", ; Class under the mouse
Menu : Menu()
}
ShouldDisplayMenu() {
MouseGetPos( , , &WinIdUnderMouse)
GTOF.WinId := WinIdUnderMouse
GTOF.Class := WinGetClass("ahk_id " . WinIdUnderMouse)
return GTOF.Class ~= "#32770|ExploreWClass|CabinetWClass|ConsoleWindowClass"
}
DestroyMenu() {
DllCall("KillTimer", "Ptr", A_ScriptHwnd, "Ptr", id := 1)
if not WinExist("ahk_id " GTOF.WinId) {
GTOF.Menu.Delete()
}
}
DisplayMenu() {
; Fresh menu, width adapts to path length every time
GTOF.Menu := Menu()
FolderMenu := GTOF.Menu
; Get current paths and build menu with them
for window in ComObject("Shell.Application").Windows {
; Exclude special locations
; Computer, Recycle Bin, Search Results, Internet Explorer pages
if InStr(window.FullName, "explorer.exe") && InStr(window.LocationURL, "file://") {
MenuItemName := window.Document.Folder.Self.Path
; Get paths of currently opened Explorer windows
FolderMenu.Add(MenuItemName, NavigateToFolder.Bind(MenuItemName))
; Same default folder icon for all
; Too difficult getting the actual icons, on the off chance they're not default
FolderMenu.SetIcon(MenuItemName, A_WinDir "\system32\imageres.dll", 4) ; imageres.dll,4 = Folder icon
}
}
; If no windows are open
OpenedWindowsCount := DllCall("GetMenuItemCount", "ptr", FolderMenu.Handle)
if not OpenedWindowsCount {
FolderMenu.Add("No folders open...", (*) => {})
FolderMenu.Disable("No folders open...")
}
; Add User profile / $HOME directory entry
FolderMenu.Add("Home", NavigateToFolder.Bind("%USERPROFILE%"))
FolderMenu.SetIcon("Home", A_WinDir "\system32\imageres.dll", 118) ; imageress.dll,118 = User folder icon
; Add Desktop entry at the end of the menu
FolderMenu.Add("Desktop", NavigateToFolder.Bind(A_Desktop))
FolderMenu.SetIcon("Desktop", A_WinDir "\system32\imageres.dll", 106) ; imageress.dll,106 = Desktop icon
; From a separate thread destroy the menu if the target Open with dialog is gone
; See thread "Script execution is stopped when menu is open"
; https://www.autohotkey.com/boards/viewtopic.php?style=17&p=478539
DllCall("SetTimer", "Ptr", A_ScriptHwnd, "Ptr", id := 1, "UInt", 1000, "Ptr", CallbackCreate(DestroyMenu, "Fast"))
; Present the menu
FolderMenu.Show()
; Destroy the menu so it doesn't remember previously opened windows
FolderMenu.Delete()
}
NavigateToFolder(ItemName, *) {
; Fetch the array element that corresponds to the selected menu item:
path := ItemName
if path = ""
return
; Activate the window so that if the user is middle-clicking
; outside the dialog, subsequent clicks will also work:
WinActivate "ahk_id " GTOF.WinId
; It's a dialog.
if GTOF.Class = "#32770" {
; Lexikos solution https://stackoverflow.com/a/25718181/5266640
; {F4} is slower because it drops down the menu of past paths
SendInput "!{d}{Raw}" path "`n"
return
}
; In Explorer, switch folders.
else if GTOF.Class ~= "(Cabinet|Explore)WClass" {
ControlClick "ToolbarWindow323", GTOF.WinId,,,, "NA x1 y1"
ControlFocus "Edit1", GTOF.WinId
ControlSetText path, "Edit1", GTOF.WinId
; Tekl reported the following: "If I want to change to Folder L:\folder
; then the addressbar shows http://www.L:\folder.com. To solve this,
; I added a {right} before {Enter}":
ControlSend "{Right}{Enter}", "Edit1", GTOF.WinId
return
}
; In a console window, navigate to that directory
else if GTOF.Class = "ConsoleWindowClass" {
WinActivate GTOF.WinId ; Because sometimes the mclick deactivates it.
SetKeyDelay 0 ; This will be in effect only for the duration of this thread.
Send "pushd " path "{Enter}"
return
}
; Since the above didn't return, one of the following is true:
; 1) It's an unsupported window type but g_AlwaysShowMenu is true.
Run "explorer " path ; Might work on more systems without double quotes.
}
; Easy Access to Currently Opened Folders
; Original author: Savage
; Fork by Leeroy
; Invoke a menu of currently opened folders when you click
; the middle mouse button inside Open / Save as dialogs or
; Console (command prompt) windows. Select one of these
; locations and the script will navigate there.
; CONFIG: CHOOSE A DIFFERENT HOTKEY
; You could also use a modified mouse button (such as ^MButton) or
; a keyboard hotkey. In the case of MButton, the tilde (~) prefix
; is used so that MButton's normal functionality is not lost when
; you click in other window types, such as a browser.
; Middle-click like original script by Savage
f_Hotkey = ~MButton
; Ctrl+G like in Listary
f_HotkeyCombo = ~^g
; END OF CONFIGURATION SECTION
; Do not make changes below this point unless you want to change
; the basic functionality of the script.
#SingleInstance, force ; Needed since the hotkey is dynamically created.
; Auto-execute section.
Hotkey, %f_Hotkey%, f_DisplayMenu
Hotkey, %f_HotkeyCombo%, f_DisplayMenu
return
; Navigate to the chosen path
f_Navigate:
; Set destination path to be the selected menu item
f_path = %A_ThisMenuItem%
if f_path =
return
if f_class = #32770 ; It's a dialog.
{
; Activate the window so that if the user is middle-clicking
; outside the dialog, subsequent clicks will also work:
WinActivate ahk_id %f_window_id%
; Alt+D to convert Address bar from breadcrumbs to editbox
Send !{d}
; Wait for focus
Sleep 50
; The control that's focused after Alt+D is thus the address bar
ControlGetFocus, addressbar, a
; Put in the chosen path
ControlSetText %addressbar%, % f_path, a
; Go there
ControlSend %addressbar%, {Enter}, a
; Return focus to filename field
ControlFocus Edit1, a
return
}
; In a console window, pushd to that directory
else if f_class = ConsoleWindowClass
{
; Because sometimes the mclick deactivates it.
WinActivate, ahk_id %f_window_id%
; This will be in effect only for the duration of this thread.
SetKeyDelay, 0
; Clear existing text from prompt and send pushd command
Send, {Esc}pushd %f_path%{Enter}
return
}
return
RemoveToolTip:
SetTimer, RemoveToolTip, Off
ToolTip
return
; Display the menu
f_DisplayMenu:
; Get active window identifiers for use in f_Navigate
WinGet, f_window_id, ID, a
WinGetClass, f_class, a
; Don't display menu unless it's a dialog or console window
if f_class not in #32770,ConsoleWindowClass
return
; Otherwise, put together the menu
GetCurrentPaths() {
For pwb in ComObjCreate("Shell.Application").Windows
; Exclude special locations like Computer, Recycle Bin, Search Results
If InStr(pwb.FullName, "explorer.exe") && InStr(pwb.LocationURL, "file:///")
{
; Get paths of currently opened Explorer windows
Menu, CurrentLocations, Add, % pwb.document.folder.self.path, f_Navigate
; Same default folder icon for all
Menu, CurrentLocations, Icon, % pwb.document.folder.self.path, %A_WinDir%\system32\imageres.dll, 4
}
}
; Get current paths and build menu with them
GetCurrentPaths()
; Don't halt the show if there are no paths and the menu is empty
Menu, CurrentLocations, UseErrorLevel
; Present the menu
Menu, CurrentLocations, Show
; If it doesn't exist show reassuring tooltip
If ErrorLevel
{
; Oh! Look at that taskbar. It's empty.
ToolTip, No folders open
SetTimer, RemoveToolTip, 1000
}
; Destroy the menu so it doesn't remember previously opened windows
Menu, CurrentLocations, Delete
return
@Acecool
Copy link

Acecool commented Dec 26, 2016

If you only have one folder open and you middle click > release middle click > left-click only folder > release left-click - it will save to the currently opened folder instead of switching to the selected folder... I just saved the web-page and wanted to save to downloads and thought it worked when it automatically closed the SaveAs window after selecting the downloads folder... But, then I opened folder location and it was the previous folder in SaveAs... When 2 folders are open, clicking on 1 actually switches the folder.

@akaleeroy
Copy link
Author

@Acecool I'm unable to reproduce this. It isn't supposed to automatically save anyway, just to take you to the folder. I've just tested a Windows 8 machine and it didn't navigate on the first try though. So maybe there is a problem with the address bar control targeting.

@akaleeroy
Copy link
Author

akaleeroy commented Jan 8, 2017

Just found out this feature is available in Listary:

Quick Switch

Are you tired of digging through a slew of open windows to work with files in a program? With Listary’s Quick Switch feature, just click Ctrl+G to instantly jump to the open folder of the file you’re working with.

▷ WATCH DEMO VIDEO

Also done in Quick Access Popup by Jean Lalonde
This software is actually an AutoHotkey project, loaded with features!

▷ Folders Popup - Switch between current folders demo

@Cr8zyIvan
Copy link

Wow! This is a really sweet code.
It works with Visual Studio Code, but doesn't seem to work with Word, Excel, or any other Program I've used it with though :(

@akaleeroy
Copy link
Author

akaleeroy commented Oct 14, 2019

@Gaxve

doesn't seem to work with Word, Excel, or any other Program I've used it with though :(

The code is simple enough for the standard Common Item Dialog. Unfortunately there are many exceptions: the old kind of dialog used by RegEdit for example, and of course custom dialogs used by various software suites (LibreOffice, Blender). These edge cases are difficult to address, especially while keeping the code simple. I haven't felt the burning need to do so, and it would take me a long time because I'm not a professional programmer.

I do use this script daily. Where it is supported it really helps. If you want to make heavy use of this functionality in a program where this doesn't work you could try the pro alternatives mentioned above, or just make do with "abusing" a clipboard manager to copy-paste paths (as long as there is an address bar).

@zzinggame
Copy link

Is there something we can do this same as Listary does
Image:

@Chyowing
Copy link

Is there a mac version of this function? Please, I need this function on Mac OS.

@Coldblackice
Copy link

Brilliant script! One of my biggest annoyances with Windows over the years. Oh how many copy/pastes I've had to alt-tab + alt-D + alt-N between. Thanks for sharing!

Copy link

ghost commented May 5, 2022

Is there something we can do this same as Listary does

by ahk v2 you can check here

global LastActiveFolder := "下載"
#HotIf WinExist("ahk_class #32770") & WinActive("ahk_exe explorer.exe")
LButton::
{
MouseGetPos , , &id, &control

for window in ComObject("Shell.Application").Windows
    If (window.LocationName == WinGetTitle(id)) {
		pwd := SubStr(window.LocationURL, 9)
		Loop
		{
		pwd := 	StrReplace(pwd, "/", "\",, &Count)
		pwd := 	StrReplace(pwd, "%20", " ",, &Count)	
		if (Count = 0)
			break
		}
		global LastActiveFolder := pwd
	}
	Send "{Click}"
}
#HotIf

#HotIf WinActive("ahk_class #32770")
^g::
{
	If (LastActiveFolder == "下載") {
	global LastActiveFolder := "C:\Users\" A_Username "\Downloads"
	} else {
	}
	WinActive("A")
	ControlFocus "Edit1"
	ControlSetText(LastActiveFolder, "Edit1")
	ControlSend "{Enter}", "Button2"
}
#HotIf

@jackusay
Copy link

jackusay commented Apr 8, 2025

FYI,

ChatGPT:

You mentioned that when the file dialog pops up and you select one of the currently open folders (from the menu), the dialog box disappears, and the file ends up being saved in the default Downloads folder, not the one you selected.

This behavior likely means that the script's ControlSetText and ControlSend {Enter} are causing the dialog to prematurely submit, so it saves to the default location instead of navigating to the intended folder.


🎯 Possible root causes:

  1. Some applications use custom (non-standard) file dialogs, so your script’s methods (Alt+D, ControlSetText, ControlSend) may behave unexpectedly or trigger the default save button immediately.
  2. The dialog controls may not be fully loaded or ready, and sending {Enter} right away might trigger the default save behavior before the path gets applied.
  3. Some apps (e.g., Chrome, Edge) use non-standard dialogs, not the usual #32770 class, so your script might not handle them properly.
  4. There’s no delay or check to confirm the address bar has focus before pressing {Enter}, which increases the chance of triggering the default action.

✅ Suggested fix

In this part of your script:

  Send !{d}
  Sleep 50
  ControlGetFocus, addressbar, a
  ControlSetText %addressbar%, % f_path, a
  ControlSend %addressbar%, {Enter}, a
  ControlFocus Edit1, a

Add some extra delay and checks to prevent accidental submission. Try this modified version:

  Send !{d}
  Sleep 100
  ControlGetFocus, addressbar, a

  if (addressbar != "")
  {
    ControlSetText %addressbar%, %f_path%, a
    Sleep 100
    ControlSend %addressbar%, {Enter}, a
    Sleep 100
    ControlFocus Edit1, a
  }
  else
  {
    ; Optional: Show a tooltip if address bar can't be detected
    ToolTip, Failed to get address bar control
    SetTimer, RemoveToolTip, 1000
  }

🧰 Extra Suggestions (Advanced):

  • Check which control is focused before sending {Enter}. Don’t send it blindly.
  • Use SetTimer or other methods to wait longer or check if the address bar is ready before sending commands.
  • To support non-standard dialogs, you might need custom handling per ahk_class (e.g., Chrome’s Save dialog is Chrome_WidgetWin_1).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment