Programmatically change path of #32770 window

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
mythofechelon
Posts: 20
Joined: 20 Jun 2018, 05:03

Programmatically change path of #32770 window

25 Oct 2020, 11:59

Is it possible to programmatically change the path of a File Explorer #32770 window via COM object or something, rather than simulating user interactions? If so, how exactly?

As per https://autohotkey.com/board/topic/102127-navigating-explorer-directories/#entry634365 and https://docs.microsoft.com/en-us/windows/win32/shell/shell, I've experimented with using the COM object Shell.Application but I've found that it only lists the existing File Explorer CabinetWClass (normal) windows, not the existing #32770 ("Open", "Save As", etc) windows open in other applications. You can see this for yourself by running the following PowerShell commands:

Code: Select all

$Shell = New-Object -ComObject Shell.Application
ForEach ($Item in $Shell.windows()) {
    Write-Host $Item.LocationName
}
Currently, I've managed to achieve this by writing the following code but, because it simulates user interactions, it's a bit too slow and inexact for my liking:

Code: Select all

If ((WinActive("ahk_class #32770")) And (WinActive("Save As") Or WinActive("Save Print Output As") Or WinActive("Open"))){
	If (NewFolderPath != ""){
		ControlGetText, CurrentFolderPath, ToolbarWindow324, A
		CurrentFolderPath := StrReplace(CurrentFolderPath, "Address: ")
		
		If (CurrentFolderPath != NewFolderPath){
			; Alt and D is a native Windows hotkey for selecting the address bar
			SendInput, !d %NewFolderPath% {Enter}
			
			; The above command doesn't seem to be synchronous so triggering ControlFocus too early won't work
			Sleep 400
			
			; Selecting the address bar changes focus from the file name box so this sets it back
			ControlFocus, Edit1, A
		}
	}
}
@kon

Thanks.



Edit 2020/10/26 12:20: I've managed to fine-tune the code to the following which speeds up the operation and makes it a bit more precise but I'd still prefer a more elegant solution if possible:

Code: Select all

If (WinActive("ahk_class #32770") And (WinActive("Save As") Or WinActive("Save Print Output As") Or WinActive("Open"))){
	If (NewFolderPath != ""){
		ControlGetText, CurrentFolderPath, ToolbarWindow324, A
		CurrentFolderPath := StrReplace(CurrentFolderPath, "Address: ")
		
		If (CurrentFolderPath != NewFolderPath){
			; Alt and D is a native Windows hotkey for selecting the address bar
			SendInput, !d 
			Sleep, 50
			ControlSetText, Edit2, %NewFolderPath%
			ControlSend, Edit2, {Enter}
			
			; Selecting the address bar changes focus from the file name box so this sets it back
			ControlFocus, Edit1, A
		}
	}
}
Kobaltauge
Posts: 264
Joined: 09 Mar 2019, 01:52
Location: Germany
Contact:

Re: Programmatically change path of #32770 window

26 Oct 2020, 14:07

I got caught by your question. Unfortunately I can't give you a solution. As I understood the issue. The #32770 is not an application window. It's a class. Therefor the Powershell script doesn't list it. Trying to modify a class via dcom is very hard (no one gave an example). Every time this question uprise, everyone is pointing to AutoIT and so to AHK.

IMHO your solution is a good way to realize your task.
User avatar
rommmcek
Posts: 1480
Joined: 15 Aug 2014, 15:18

Re: Programmatically change path of #32770 window

26 Oct 2020, 15:16

IMHO mythofechelon's way is not the best solution.
Changing the focus and sleep for arbitrarily short period of time might cause problem under CPU load, so better is to check if change has really occurred (if you're not comfortable with larger sleep).
However why change the focus at all. Modern windows dialogs will accept path in the "File name" control too, so try:

Code: Select all

ControlSetText, Edit1, %NewFolderPath%, A
ControlSend, Edit1, {Enter}, A
mythofechelon
Posts: 20
Joined: 20 Jun 2018, 05:03

Re: Programmatically change path of #32770 window

26 Oct 2020, 17:11

I know next to nothing about Win32 / WinAPI but I was curious so, earlier today, I read into and/or experimented with the following things: Unfortunately, none of them worked, probably because none of them are designed for this.

@Kobaltauge: Thanks for your input.

@rommmcek:
  • Yes, I considered that but it doesn't work without a small sleep and I couldn't find any documented methods of making SendInput properly synchronous / waiting until it's completed.
  • That would work for some use cases but I want to see the folder contents, not just save to a folder.
Thanks.
User avatar
rommmcek
Posts: 1480
Joined: 15 Aug 2014, 15:18

Re: Programmatically change path of #32770 window

26 Oct 2020, 18:56

Nice find, it actually works:

Code: Select all

DllCall("SetCurrentDirectory", "Str","C:\Users\")
Run, Cmd
However, third party apps most probably use it too, so you cannot have influence from outside.
@1 Try this approach:

Code: Select all

If WinActive("ahk_class #32770") && (WinActive("Save As") || WinActive("Save Print Output As") || WinActive("Open")) {
    If (NewFolderPath != "") {
        ControlGetText, CurrentFolderPath, ToolbarWindow324, A
        CurrentFolderPath := StrReplace(CurrentFolderPath, "Address: ")
            
        If (CurrentFolderPath != NewFolderPath) {
            While (cF!="Edit2" && A_Index < 199) {
                SendInput, !d
                ControlGetFocus, cF, A
            }   cF:= ""
            ControlSetText, Edit2, %NewFolderPath%, A
            ControlSend, Edit2, {Enter}, A
            While (cF!=NewFolderPath && A_Index < 99) {
                SendInput, !d
                ControlGetText, cF, Edit2, A
            }   cF:= ""
            While (cF!="Edit1" && A_Index < 99) {
                ControlFocus, Edit1, A
                ControlGetFocus, cF, A
            }   cF:= ""
        }
    }
}
@2 ... will accept path ... (w/o file name):

Code: Select all

If WinActive("ahk_class #32770") && (WinActive("Save As") || WinActive("Save Print Output As") || WinActive("Open")) {
	If (NewFolderPath != "") {
		ControlGetText, CurrentFolderPath, ToolbarWindow324, A
		CurrentFolderPath := StrReplace(CurrentFolderPath, "Address: ")
		
		If (CurrentFolderPath != NewFolderPath) {
            		ControlSetText, Edit1, %NewFolderPath%, A
            		ControlSend, Edit1, {Enter}, A
        	}
    	}
}
mythofechelon
Posts: 20
Joined: 20 Jun 2018, 05:03

Re: Programmatically change path of #32770 window

27 Oct 2020, 14:31

@rommmcek

Oh, yeah! I read that it only works for the current process, though, so it doesn't seem to be useful for this use case.

I completely forgot that you can enter a path into the file name field! Nice one! I've built off of that and now have the following which seems faster and more effective:

Code: Select all

If (WinActive("ahk_class #32770") And (WinActive("Save As") Or WinActive("Save Print Output As") Or WinActive("Open"))){
	If (NewFolderPath != ""){
		ControlGetText, CurrentFolderPath, ToolbarWindow324
		CurrentFolderPath := StrReplace(CurrentFolderPath, "Address: ")
		
		If (CurrentFolderPath != NewFolderPath){
			ControlFocus, Edit1 ; Just in case you click out of the file name field
			ControlSetText, Edit1, %NewFolderPath%
			ControlSend, Edit1, {Enter}
			
			Loop {
				ControlGetText, File_Name, Edit1
				
				If (NewFolderPath != File_Name){
					Break
				}
			}

			[more stuff]
		}
	}
}
william_ahk
Posts: 502
Joined: 03 Dec 2018, 20:02

Re: Programmatically change path of #32770 window

14 Nov 2022, 04:34

Setting Edit1 is no good because in a Save As dialog the file will be saved as Enter is pressed, leaving no chance for choosing subfolders if you need to.

I find the hotkey method to be the best. Works all the time, also no loop wait is needed.

Code: Select all

filepath := A_Desktop
fileselect_window := "ahk_class #32770"
ControlSend,, {Ctrl down}{l down}{l up}{Ctrl up}, % fileselect_window
ControlSetText, Edit2, % filepath, % fileselect_window
ControlSend, Edit2, {Enter}, % fileselect_window
ControlFocus, Edit1, % fileselect_window
User avatar
Xtra
Posts: 2750
Joined: 02 Oct 2015, 12:15

Re: Programmatically change path of #32770 window

14 Nov 2022, 04:43

Setting Edit1 is no good because in a Save As dialog the file will be saved as Enter is pressed, leaving no chance for choosing subfolders if you need to.
Send or set the full file path in Edit1. No need to change to subfolders.
william_ahk
Posts: 502
Joined: 03 Dec 2018, 20:02

Re: Programmatically change path of #32770 window

14 Nov 2022, 04:47

@Xtra I mean in a Save As dialog, where the filename and subfolder is not predetermined.
User avatar
boiler
Posts: 17279
Joined: 21 Dec 2014, 02:44

Re: Programmatically change path of #32770 window

14 Nov 2022, 06:53

What might not be clear is this: Are you trying to change the folder displayed as a starting point so that the user can then make selections from there? That seems to be the source of confusion.
william_ahk
Posts: 502
Joined: 03 Dec 2018, 20:02

Re: Programmatically change path of #32770 window

14 Nov 2022, 10:10

@boiler Yes, you explained it perfectly.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Google [Bot] and 162 guests