GP SoftwareTwitter
Opus FAQsManualCommandsObjects

Navigate old Windows Folder Browser dialog to DOpus source location

I was browsing the Tools section and saw this post: Change Windows Open Save Dialog to Dopus lister location
When I read the title, I got all excited because for some reason I thought they were talking about these horrible, ghastly, unreasonable folder browsers that only have a TreeView and no Edit control*
Capture 2020-06-15 04-19-33

But they were talking about the good, easy kind that already has an Edit control for the target path.
But that got me thinking and made me want to be able to paste DOpus's source path to those old dialogs as well.

Like the above post, this is an AHK script and is very much inspired by their idea.
However, since we have nothing to directly input our path and have to use the treeView (unless you can send a window message to the dialog that tells it to navigate to a given path?), I use keyboard navigation to type the path segments and expand them as we go along.

Known limitations:

  • Network drives might have cumbersome names (like "FolderName (\\localhost\N$) (E:)") that I can't easily adapt to
    I worked around this by letting the user manually select the desired drive, the rest will then continue automatically again.
  • Hard drives might have spun down and the dialog might therefore not be ready for further navigation.
    I worked around this by awaiting the successful creation of a dummy file. it's not ideal but I find it nicer than what I had before (switch to ask user to continue when ever the contents were loaded)
#IfWinActive, ahk_class #32770
^!v::
	waitDuration := 50 ; time between inputs
	DOpusRTPath := "C:\Program Files\GPSoftware\Directory Opus\dopusrt.exe" ; Location of dopusrt.exe
	lan := "en" ; Your system language
	computerLangs := {"en": "This PC", "de": "Dieser PC"} ; what is the "root" called? e.g. "Computer" in Win7, "This PC" in WIn10
	driveLabelFormat := "$label ($letter)" ; how are your drive names formatted? e.g. "Movies (I:)" -> "$label ($letter)"
	treeViewClassName := "SysTreeView321" ; don't know where the 321 comes from, but the occurrences of the old folder browser dialog I could find were all using that class
	
	keyWait, ctrl, 1
	WinGet, curwindow_controllist, ControlList, A
	
	If(InStr(curwindow_controllist, "SHBrowseForFolder ShellNameSpace Control1") && InStr(curwindow_controllist, treeViewClassName)){
		oldclip := clipboard
		Clipboard := "" ; empty the clipboard so ClipWait has something to wait for
		Run, "%DOpusRTPath%" /cmd Clipboard SET {sourcepath$}
		ClipWait 1.0
		path := Clipboard
		clipboard := oldclip
		
		If(ErrorLevel){
			MsgBox, Could not get sourcepath from Dopus
			Return
		}
		If(SubStr(path,0,1)=""""){
			StringTrimLeft, path, path, 1
		}
		If(SubStr(path,StrLen(path),1)=""""){
			StringTrimRight, path, path, 1
		}
		
		computer := computerLangs[lan]
		if(InStr(path, ":") == 2)
			drv := substr(path, 1,2)
		else{
			msgbox, The path does not seem to start with a drive letter:`n%path%
			return
		}
		
		controlFocus, %treeViewClassName%, A
		send, {home}
		sleep, %waitDuration%
		send, %computer%
		sleep, %waitDuration%
		send, {right}
		sleep, %waitDuration%
		
		DriveGet, driveLabel, Label , %drv%
		DriveGet, type, Type, %drv%
		if(type=="Network"){
			msgBox, %drv% seems to be a network drive, which is hard to account for.`nPlease expand that drive manually, make sure the contents are loaded and then click "OK"
			sleep, %waitDuration%
		}
		else{
			driveLabel := strReplace(driveLabelFormat, "$label", driveLabel)
			driveLabel := strReplace(driveLabel, "$letter", drv)
			sendRaw, %driveLabel%
			
			if(strlen(path)==2 || (strlen(path)==3 && substr(path,3) == "\")){
				return
			}
			
			sleep, %waitDuration%
			send, {right}
			if(!makeSureDriveIsUp(drv)){
				msgbox, Drive timed out: %drv%
				return
			}
			
		}
		
		dirs := strsplit(substr(path, 3), "\")
		first := true
		for i,v in dirs {
			if(v!=""){
				if(first)
					first := false
				else
					send, {right}
				sleep, %waitDuration%
				sendRaw, %v%
				sleep, %waitDuration%
			}
		}
	} Else {
		Send, ^!v
	}
Return

CreateTempFile(PathName, Prefix := "AHK"){
	VarSetCapacity(TmpFileName, 524, 0)
	If DllCall("Kernel32.dll\GetTempFileName", "Ptr", &PathName, "Ptr", &Prefix, "UInt", 0, "Str", TmpFileName, "UInt")
		Return TmpFileName
	Return ""
}

makeSureDriveIsUp(drv, maxTimeout := 10000){
	sleepInterval := 200
	While !(TmpFileName := CreateTempFile(drv)){
		if(maxTimeout<=0)
			return false
		maxTimeout -= sleepInterval
		Sleep, sleepInterval
	}
	Filedelete, %TmpFileName%
	return true
}
#IfWinActive

*well, there is an Edit control hidden, but that seems to be for (re)naming folders in the TreeView, not for returning a target path

2 Likes