|
#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. |
|
} |
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
andControlSend {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:
Alt+D
,ControlSetText
,ControlSend
) may behave unexpectedly or trigger the default save button immediately.{Enter}
right away might trigger the default save behavior before the path gets applied.#32770
class, so your script might not handle them properly.{Enter}
, which increases the chance of triggering the default action.✅ Suggested fix
In this part of your script:
Add some extra delay and checks to prevent accidental submission. Try this modified version:
🧰 Extra Suggestions (Advanced):
{Enter}
. Don’t send it blindly.SetTimer
or other methods to wait longer or check if the address bar is ready before sending commands.ahk_class
(e.g., Chrome’s Save dialog isChrome_WidgetWin_1
).