Re: 4 options to change the current folder in Windows Explor
Posted: 07 Feb 2014, 12:42
Works great on 8.1. No modifications.
Let's help each other out
https://www.autohotkey.com/boards/
The Shell.Application COM object is only opening or controling Explorr windows. For dialog boxes, you have to send commands to dialog box control and Send some keys.Azevedo wrote:Hi.
It works fine on a regular windows explorer window but it won't work on Open/Save dialogs.
Any help?
Thanks
Code: Select all
;------------------------------------------------------------
NavigateDialog(strPath, strWinId, strClass)
;------------------------------------------------------------
/*
Excerpt from RMApp_Explorer_Navigate(FullPath, hwnd="") by Learning One
http://ahkscript.org/boards/viewtopic.php?f=5&t=526&start=20#p4673
*/
{
if (strClass = "#32770")
if ControlIsVisible("ahk_id " . strWinId, "Edit1")
strControl := "Edit1"
; in standard dialog windows, "Edit1" control is the right choice
Else if ControlIsVisible("ahk_id " . strWinId, "Edit2")
strControl := "Edit2"
; but sometimes in MS office, if condition above fails, "Edit2" control is the right choice
Else ; if above fails - just return and do nothing.
{
if (blnDiagMode)
Diag("NavigateDialog", "Error: #32770 Edit1 and Edit2 controls not visible")
return
}
Else if InStr(strClass, "bosa_sdm_") ; for some MS office dialog windows, which are not #32770 class
if ControlIsVisible("ahk_id " . strWinId, "Edit1")
strControl := "Edit1"
; if "Edit1" control exists, it is the right choice
Else if ControlIsVisible("ahk_id " . strWinId, "RichEdit20W2")
strControl := "RichEdit20W2"
; some MS office dialogs don't have "Edit1" control, but they have "RichEdit20W2" control, which is then the right choice.
Else ; if above fails, just return and do nothing.
{
if (blnDiagMode)
Diag("NavigateDialog", "Error: bosa_sdm Edit1 and RichEdit20W2 controls not visible")
return
}
Else ; in all other cases, open a new Explorer and return from this function
{
ComObjCreate("Shell.Application").Explore(strPath)
; http://msdn.microsoft.com/en-us/library/windows/desktop/bb774073%28v=vs.85%29.aspx
if (blnDiagMode)
Diag("NavigateDialog", "Not #32770 or bosa_sdm: open New Explorer")
return
}
if (blnDiagMode)
{
Diag("NavigateDialogControl", strControl)
Diag("NavigateDialogPath", strPath)
}
;===In this part (if we reached it), we'll send strPath to control and restore control's initial text after navigating to specified folder===
ControlGetText, strPrevControlText, %strControl%, ahk_id %strWinId% ; we'll get and store control's initial text first
ControlSetTextR(strControl, strPath, "ahk_id " . strWinId) ; set control's text to strPath
ControlSetFocusR(strControl, "ahk_id " . strWinId) ; focus control
if (WinExist("A") <> strWinId) ; in case that some window just popped out, and initialy active window lost focus
WinActivate, ahk_id %strWinId% ; we'll activate initialy active window
;=== Avoid accidental hotkey & hotstring triggereing while doing SendInput - can be done simply by #UseHook, but do it if user doesn't have #UseHook in the script ===
If (A_IsSuspended)
blnWasSuspended := True
if (!blnWasSuspended)
Suspend, On
SendInput, {End}{Space}{Backspace}{Enter} ; silly but necessary part - go to end of control, send dummy space, delete it, and then send enter
if (!blnWasSuspended)
Suspend, Off
Sleep, 70 ; give some time to control after sending {Enter} to it
ControlGetText, strControlTextAfterNavigation, %strControl%, ahk_id %strWinId% ; sometimes controls automatically restore their initial text
if (strControlTextAfterNavigation <> strPrevControlText) ; if not
ControlSetTextR(strControl, strPrevControlText, "ahk_id " . strWinId) ; we'll set control's text to its initial text
if (WinExist("A") <> strWinId) ; sometimes initialy active window loses focus, so we'll activate it again
WinActivate, ahk_id %strWinId%
if (blnDiagMode)
Diag("NavigateDialog", "Finished")
}
;------------------------------------------------------------
ControlIsVisible(strWinTitle, strControlClass)
/*
Adapted from ControlIsVisible(WinTitle,ControlClass) by Learning One
http://ahkscript.org/boards/viewtopic.php?f=5&t=526&start=20#p4673
*/
;------------------------------------------------------------
{ ; used in Navigator
ControlGet, blnIsControlVisible, Visible, , %strControlClass%, %strWinTitle%
return blnIsControlVisible
}
;------------------------------------------------------------
;------------------------------------------------------------
ControlSetFocusR(strControl, strWinTitle = "", intTries = 3)
/*
Adapted from RMApp_ControlSetFocusR(Control, WinTitle="", Tries=3) by Learning One
http://ahkscript.org/boards/viewtopic.php?f=5&t=526&start=20#p4673
*/
;------------------------------------------------------------
{ ; used in Navigator. More reliable ControlSetFocus
Loop, %intTries%
{
ControlFocus, %strControl%, %strWinTitle% ; focus control
Sleep, % (50 * intTries) ; JL added "* intTries"
ControlGetFocus, strFocusedControl, %strWinTitle% ; check
if (strFocusedControl = strControl) ; if OK
{
if (blnDiagMode)
Diag("ControlSetFocusR Tries", A_Index)
return True
}
}
}
;------------------------------------------------------------
;------------------------------------------------------------
ControlSetTextR(strControl, strNewText = "", strWinTitle = "", intTries = 3)
/*
Adapted from from RMApp_ControlSetTextR(Control, NewText="", WinTitle="", Tries=3) by Learning One
http://ahkscript.org/boards/viewtopic.php?f=5&t=526&start=20#p4673
*/
;------------------------------------------------------------
{ ; used in Navigator. More reliable ControlSetText
Loop, %intTries%
{
ControlSetText, %strControl%, %strNewText%, %strWinTitle% ; set
Sleep, % (50 * intTries) ; JL added "* intTries"
ControlGetText, strCurControlText, %strControl%, %strWinTitle% ; check
if (strCurControlText = strNewText) ; if OK
{
if (blnDiagMode)
Diag("ControlSetTextR Tries", A_Index)
return True
}
}
}
;------------------------------------------------------------
Oh I see... well ok, I'll do with the send commands then!The Shell.Application COM object is only opening or controling Explorr windows. For dialog boxes, you have to send commands to dialog box control and Send some keys.
See this script and search for NavigateDialog(strPath, strWinId, strClass) close to the end of the script.
Here is an abstract of the code (this will not work by itself but you have the ingredients):
Code: Select all
For pExp in ComObjCreate("Shell.Application").Windows
if (pExp.hwnd = strWinId)
try pExp.Navigate(myPath)
Code: Select all
Send, {F4}{Esc}
Sleep, 500 ; long delay for safety
Send, %strFolder%{Enter}
Code: Select all
run, Explorer.exe
Sleep, 500
Send, {F4}{Esc}
Sleep, 500
Send, c:\delete_me{Enter}
Code: Select all
run, Explorer.exe
Sleep, 500
Send, {F4}{Esc}
Sleep, 500
Send, c:\delete#me{Enter}
Code: Select all
run, Explorer.exe
Sleep, 500 ; long delay for safety
strFolder := A_ScriptDir
Send, {F4}{Esc}
Sleep, 500 ; long delay for safety
ControlSetText, Edit1, C:\delete#me, A
ControlSend, Edit1, {Enter}, A
Code: Select all
; Test script: navigate the "Computer" window to a path containing #.
FileCreateDir C:\C#Projects
for window in ComObjCreate("Shell.Application").Windows
try
if window.LocationName = "Computer"
window.Navigate("C:\C#Projects")
Thanks for jumping in Lekikos. Yes, I realized that later in my AHK learning curve . Just forgot to update this thread about it.lexikos wrote:Your Send code fails because # is the modifier symbol for the Win key. You can use {#} or SendRaw c:\delete#me`n (not {Enter}) instead.
You script also worked for me (after I adapted window.LocationName = "Computer" to my environment. But could you try the following and tell me if Alt-2 is running well for you? For me, it still produced an error. Would it be related to # being a special AHK char?lexikos wrote:However, window.Navigate("C:\C#Projects") works just fine for me on Windows 7.
Code: Select all
; this will create 2 folders at the root of your C: drive
myPath1 := "C:\delete_me\"
myPath2 := "C:\delete#me\"
if !FileExist(myPath1)
FileCreateDir, %myPath1%
if !FileExist(myPath2)
FileCreateDir, %myPath2%
run, Explorer.exe
return
!1::
!2::
strWinId := WinExist("A")
TrayTip, %myPath1%, %strWinId%
For pExp in ComObjCreate("Shell.Application").Windows
if (pExp.hwnd = strWinId)
try pExp.Navigate(A_ThisHotkey = "!1" ? "C:\delete_me\" : "C:\delete#me\")
return
# is special only for Send and hotkeys. No character in a quoted literal string has special meaning, except ` and ".Would it be related to # being a special AHK char?
Code: Select all
Navigate(Exp, Path)
{
if !RegExMatch(Path, "^.*#[^\\]*(?=\\|$)", safe_path)
safe_path := Path
Exp.Navigate(safe_path)
rem_path := SubStr(Path, StrLen(safe_path) + 2) ; Could be "", which is okay
Loop, Parse, rem_path, \
{
while Exp.ReadyState != 4
Sleep 10
item := Exp.Document.Folder.Items.Item(A_LoopField)
if !item || !item.IsFolder
throw Exception("Folder not found", -1, A_LoopField)
item.InvokeVerbEx("open")
}
}
Code: Select all
Navigate(Exp, Path)
{
if RegExMatch(Path, "#.*\\")
{
; Workaround required
WinGetPos x, y, w, h
WinClose
Run %Path%
WinWait %Path% ahk_exe explorer.exe
WinMove,,, x, y, w, h
}
else
Exp.Navigate(Path)
}
Code: Select all
Navigate(Exp, Path)
{
if RegExMatch(Path, "#.*\\")
SendInput {F4}{Esc}{Raw}%Path%`n
else
Exp.Navigate(Path)
}
Code: Select all
if vDir contains #
Loop, %vDir%, 2, 0 ;(0/1/2=files/both/folders, 0/1=recurse no/yes)
vDir := A_LoopFileShortPath
Code: Select all
;links:
;Explorer Windows Manipulations - Page 5 - Scripts and Functions - AutoHotkey Community
;https://autohotkey.com/board/topic/19039-explorer-windows-manipulations/page-5#entry297581
;Navigate2 Method (IWebBrowser2)
;https://msdn.microsoft.com/en-us/library/aa752134(v=vs.85).aspx
;4 options to change the current folder in Windows Explorer - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=5&t=526
;windows - Navigate Shell command not working when the path includes an hash - Stack Overflow
;https://stackoverflow.com/questions/22868546/navigate-shell-command-not-working-when-the-path-includes-an-hash
;an AutoHotkey v1.1 script
;note: will create folder: %A_Desktop%\abc#def\abc#def
q:: ;explorer - navigate to folder (tested on Windows 7)
WinGet, hWnd, ID, A
WinGetClass, vWinClass, % "ahk_id " hWnd
if !(vWinClass = "CabinetWClass") && !(vWinClass = "ExploreWClass")
return
vDir = %A_Desktop%\abc#def\abc#def
;vDir = %A_Desktop%\abc def\abc def
if !FileExist(vDir)
FileCreateDir, % vDir
DllCall("shell32\SHParseDisplayName", WStr,vDir, Ptr,0, PtrP,vPIDL, UInt,0, Ptr,0)
for oWin in ComObjCreate("Shell.Application").Windows
if (oWin.HWND = hWnd)
{
if !InStr(vDir, "#")
oWin.Navigate(vDir)
else
{
VarSetCapacity(SAFEARRAY, A_PtrSize=8?32:24, 0)
NumPut(1, SAFEARRAY, 0, "UShort") ;cDims
NumPut(1, SAFEARRAY, 4, "UInt") ;cbElements
NumPut(vPIDL, SAFEARRAY, A_PtrSize=8?16:12, "Ptr") ;pvData
NumPut(DllCall("shell32\ILGetSize", Ptr,vPIDL, UInt), SAFEARRAY, A_PtrSize=8?24:16, "Int") ;rgsabound[1]
oWin.Navigate2(ComObject(0x2011,&SAFEARRAY))
DllCall("shell32\ILFree", Ptr,vPIDL)
}
break
}
return