Jump to content

Recommended Posts

Posted (edited)

prologue

On the occasion of  @TheDcoder  post  (I wonder if someone can port it to AutoIt :lol: )
and because in the past I already had something similar (Active_SaveFileDlg),
( in which I remember making an effort so that it wouldn't catch windows other than Scite's)
So I took it as a challenge.  :rambo:

Of course, since I don't know much, I skipped the extras and stuck to the basics :lol:


A brief description

While the script is running in the background when you display the SaveFileDlg or OpenFileDlg window,  display a button-icon in the center of the window title.
Click it brings up a list of some favorite path plus the paths from all open folders.
by selecting one of them, WindowDlg goes to the selected path.

Covers almost everything modern SaveFileDlg & OpenFileDlg & SaveFolderDlg & OpenFolderDlg
and a series of old-style dialogs like Koda, Crimson Editor, IrfanView, etc

Active_FileDlg.au3

#NoTrayIcon
; https://www.autoitscript.com/forum/topic/212478-active_filedlg
;----------------------------------------------------------------------------------------
; Title...........: Active_FileDlg.au3
; Description.....: Add All open folder & some extra as contex menu in SaveFileDlg & OpenFileDlg
; AutoIt Version..: 3.3.16.1   Author: ioa747
;----------------------------------------------------------------------------------------
#AutoIt3Wrapper_Res_Description=Add All open folder & some extra as contex menu in SaveFileDlg & OpenFileDlg
#AutoIt3Wrapper_Res_ProductName=Active_FileDlg.au3
#AutoIt3Wrapper_Icon=shell32-68.ico
#AutoIt3Wrapper_AU3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7
#AutoIt3Wrapper_Res_Fileversion=0.0.0.5
;~ #AutoIt3Wrapper_UseX64=y

#include <WindowsConstants.au3>
#include <ButtonConstants.au3>
#include <WinAPISysWin.au3>
#include <Misc.au3>
#include <GuiTreeView.au3>
#include <Array.au3>

; Favorites folder
Global $aFavFolder[4]
$aFavFolder[0] = 3
$aFavFolder[1] = @DesktopDir        ; * <--------- Fav1 folder (get one of your own)
$aFavFolder[2] = @MyDocumentsDir    ; * <--------- Fav2 folder (get one of your own)
$aFavFolder[3] = @UserProfileDir    ; * <--------- Fav3 folder (get one of your own)

_CmdLineWatcher()

While 1
    _main()
    Sleep(500)
WEnd

Exit

;--------------------------------------------------------------------------------------------------------------------------------
Func _main()
    If WinActive("[CLASS:#32770]") Then
        Local $hWnd = WinGetHandle("[ACTIVE]")

        ; checck if gui all redy exist for this Dlg
        If WinExists("GUI-" & $hWnd) Then Return

        Local $Executable = @Compiled ? '"' & @ScriptFullPath & '"' : '"' & @AutoItExe & '" "' & @ScriptFullPath & '"'

        ;specify FileDlg criteria
        _AddressBarPath($hWnd)

        If @error Then ; alternative methods

            ; ### [2] _AltName()
            Local $sText = WinGetText($hWnd)
            If StringInStr($sText, "File &name") Then
                ; FoldersGUI($hWnd, 2)
                Run($Executable & ' FoldersGUI ' & $hWnd & ' 2')
                WinWaitActive("GUI-" & $hWnd, "", 5)
            EndIf

            ; ### [3] _BrowseForFolder()
            $sText = WinGetText($hWnd)
            If StringInStr($sText, "Select a directory") Then
                ; FoldersGUI($hWnd, 3)
                Run($Executable & ' FoldersGUI ' & $hWnd & ' 3')
                WinWaitActive("GUI-" & $hWnd, "", 5)
            EndIf

        Else
            ; ### [1] _AddressBarPath()
            ; FoldersGUI($hWnd, 1)
            Run($Executable & ' FoldersGUI ' & $hWnd & ' 1')
            WinWaitActive("GUI-" & $hWnd, "", 5)
        EndIf

    EndIf
EndFunc   ;==>_main
;----------------------------------------------------------------------------------------
Func FoldersGUI($hWnd, $iFlag)
    ; $iFlag:  1=_AddressBarPath, 2=_AltName, 3=_BrowseForFolder

    ; if parameter coming from cmdline as text
    If Not IsHWnd($hWnd) Then $hWnd = HWnd($hWnd)
    If Not IsInt($iFlag) Then $iFlag = Int($iFlag)

    Local $hGUI = GUICreate("GUI-" & $hWnd, 24, 24, -50, -50, $WS_POPUP, BitOR($WS_EX_TOOLWINDOW, $WS_EX_NOACTIVATE), $hWnd)
    Local $idDummy = GUICtrlCreateDummy()
    Local $idButton = GUICtrlCreateButton("contex button", 0, 0, 24, 24, $BS_ICON)
    GUICtrlSetImage(-1, "shell32.dll", -68)

    Local $idContext = GUICtrlCreateContextMenu($idButton)
    Local $OpenFolders = _EnumAllOpenFolder()

    ;If not open folder, just add fav
    If $OpenFolders[0][0] = 0 Then
        ReDim $OpenFolders[UBound($OpenFolders) + 1][2]
    Else
        _ArrayInsert($OpenFolders, 1, "0|") ; separator
    EndIf

    ; Add Fav folder (the numbers on the front don't matter)
    For $i = 1 To $aFavFolder[0]
        _ArrayInsert($OpenFolders, 1, $i & "|" & $aFavFolder[$i])
    Next

    $OpenFolders[0][0] = UBound($OpenFolders) - 1
    ;_ArrayDisplay($OpenFolders)

    ; Create Context Menu
    For $i = 1 To $OpenFolders[0][0]
        GUICtrlCreateMenuItem($OpenFolders[$i][1], $idContext)
    Next

    Local $Wpos = WinGetPos($hWnd)
    WinMove($hGUI, "", $Wpos[0] + $Wpos[2] * 0.5, $Wpos[1] + 3)
    Sleep(50)
    GUISetState(@SW_SHOWNOACTIVATE, $hGUI)

    WinActivate($hWnd)
    Local $MsgId

    While WinExists($hWnd)
        $Wpos = WinGetPos($hWnd)
        WinMove($hGUI, "", $Wpos[0] + $Wpos[2] * 0.5, $Wpos[1] + 3)

        $MsgId = GUIGetMsg()
        Switch $MsgId
            Case 6 To $OpenFolders[0][0] + 6
                Switch $iFlag
                    Case 1
                        _AddressBarPath($hWnd, $OpenFolders[$MsgId - 5][1])
                    Case 2
                        _AltName($hWnd, $OpenFolders[$MsgId - 5][1])
                    Case 3
                        _BrowseForFolder($hWnd, $OpenFolders[$MsgId - 5][1])
                EndSwitch

            Case $idButton
                GUICtrlSendToDummy($idDummy)
            Case $idDummy
                MouseClick("right")
        EndSwitch
    WEnd

    GUIDelete($hGUI)

    Exit

EndFunc   ;==>FoldersGUI
;----------------------------------------------------------------------------------------
Func _EnumAllOpenFolder() ; enumerating all open folders
    Local $oShell = ObjCreate("Shell.Application")
    Local $sPath, $index = 0
    Local $aArray[$oShell.Windows.Count + 1][2] = [["hWnd", "Path"]]
    For $oWin In $oShell.Windows
        $index += 1
        $aArray[0][0] = $index
        $sPath = StringTrimLeft($oWin.LocationURL, 8) ; trim 'file:///'
        $sPath = StringReplace($sPath, "/", "\")
        $sPath = _UnicodeURLDecode($sPath)
        $aArray[$index][0] = HWnd($oWin.HWND)
        $aArray[$index][1] = $sPath
    Next
    Return $aArray
EndFunc   ;==>_EnumAllOpenFolder
;----------------------------------------------------------------------------------------
Func _UnicodeURLDecode($toDecode)
    Local $strChar = "", $iOne, $iTwo
    Local $aryHex = StringSplit($toDecode, "")
    For $i = 1 To $aryHex[0]
        If $aryHex[$i] = "%" Then
            $i = $i + 1
            $iOne = $aryHex[$i]
            $i = $i + 1
            $iTwo = $aryHex[$i]
            $strChar = $strChar & Chr(Dec($iOne & $iTwo))
        Else
            $strChar = $strChar & $aryHex[$i]
        EndIf
    Next
    Local $Process = StringToBinary($strChar)
    Local $DecodedString = BinaryToString($Process, 4)
    Return $DecodedString
EndFunc   ;==>_UnicodeURLDecode
;----------------------------------------------------------------------------------------
Func _AddressBarPath($hWnd, $sNewBarPath = "")
    WinActivate($hWnd)
    For $i = 1 To 10
        Local $hCtrl = ControlGetHandle($hWnd, "", "ToolbarWindow32" & $i)
        If @error Then ExitLoop
        Local $sControlText = ControlGetText($hWnd, "", $hCtrl)
        If StringLeft($sControlText, 9) = "Address: " Then
            Local $aTextPart = StringSplit($sControlText, ": ", 1)
            If $aTextPart[0] = 2 Then
                ; Get AddressBarPath
                If $sNewBarPath == "" Then
                    Return $aTextPart[2]
                Else ; Set AddressBarPath
                    ControlCommand($hWnd, "", $hCtrl, "SendCommandID", 1280)
                    Local $sCtrlNN = ControlGetFocus($hWnd)
                    Local $hCtrlHnd = ControlGetHandle($hWnd, "", $sCtrlNN)
                    ControlSetText($hWnd, "", $hCtrlHnd, $sNewBarPath)
                    ControlSend($hWnd, "", $hCtrlHnd, "{ENTER}")
                    Return $sNewBarPath
                EndIf
            EndIf
        EndIf
    Next

    ; If Error, return an empty string
    Return SetError(1, 0, "")
EndFunc   ;==>_AddressBarPath
;----------------------------------------------------------------------------------------
Func _AltName($hWnd, $sNewBarPath)
    WinActivate($hWnd)
    ControlSend($hWnd, "", "", "!n") ; File &name ;File &name:
    Local $sCtrlNN = ControlGetFocus($hWnd)
    Local $hCtrlHnd = ControlGetHandle($hWnd, "", $sCtrlNN)
    ControlSetText($hWnd, "", $hCtrlHnd, $sNewBarPath)
    ControlSend($hWnd, "", $hCtrlHnd, "{ENTER}")
    Return $sNewBarPath
EndFunc   ;==>_AltName
;----------------------------------------------------------------------------------------
Func _BrowseForFolder($hWnd, $sNewBarPath)
    WinActivate($hWnd)
    Local $hTView = ControlGetHandle($hWnd, "", "SysTreeView321")
    Local $aPath = StringSplit($sNewBarPath, "\", 1)

    ; first find drive (with label)
    Local $hItemFound = _GUICtrlTreeView_FindItem($hTView, $aPath[1], True)
    If $hItemFound Then _GUICtrlTreeView_SelectItem($hTView, $hItemFound)
    Sleep(10)
    Local $sSPath = $aPath[1]
    Local $hItemOld = $hItemFound
    For $i = 2 To $aPath[0]
        $hItemFound = _GUICtrlTreeView_FindItem($hTView, $aPath[$i], False, $hItemOld)
        $hItemOld = $hItemFound
        $sSPath &= "\" & $aPath[$i]
        If $hItemFound Then _GUICtrlTreeView_SelectItem($hTView, $hItemFound)
        Sleep(10)
    Next

    If $sSPath = $sNewBarPath Then
        ;ControlSend($hWnd, "", $hTView, "{ENTER}")
        Return $sNewBarPath
    EndIf

EndFunc   ;==>_BrowseForFolder
;----------------------------------------------------------------------------------------
Func _CmdLineWatcher()
    ; Run('"' & @AutoItExe & '" "' & @ScriptFullPath & '" FoldersGUI ' & $hWnd & ' 1')
    Local $aArgs = $CmdLine
    Local $sFunc
    If $aArgs[0] > 0 Then
        $sFunc = $aArgs[1]
        _ArrayDelete($aArgs, 1)
        $aArgs[0] = "CallArgArray"
        Call($sFunc, $aArgs)
        If @error = 0xDEAD And @extended = 0xBEEF Then
            ToolTip("error !! Function does not exist" & @CRLF & "or wrong number of parameter", Default, Default, @ScriptName, 3)
            Sleep(4000)
            ToolTip("")
        EndIf
        Exit
    EndIf

EndFunc   ;==>_CmdLineWatcher
;----------------------------------------------------------------------------------------

 

Please, every comment is appreciated!
leave your comments and experiences here!
Thank you very much  :)

 

 

Edited by ioa747
UpDate to version 0.0.0.5

I know that I know nothing

Posted (edited)

I used to use a program named FolderMenu (on my PC) a lot. I knew it was written in AutoIt ...

This post remided me of it and i started googling for it and to my surprise ... there is a sourcecode available at

https://github.com/Silvernine0S/FolderMenu3EX/tree/master

I haven't tested it yet.
It worked very well with almost every save/open dialog (with rare exceptions)

As for your code ... it would be nice if it worked with more dialogs, so far chrome save as and crimson editor are not working.

Edited by Dan_555

Some of my script sourcecode

Posted (edited)

This is the first approach,
which covers almost everything modern SaveFileDlg & OpenFileDlg & SaveFolderDlg & OpenFolderDlg
It doesn't cover programs with elevated rights, as I didn't want to give it admin rights
It does not cover improvised or boxed dialogue (like qt application)
In the meantime I thought, if something comes up that I consider essential, I can add it and upgrade my script with a new version

in chrome save as it works for me. I just tried it
in the crimson editor it doesn't work for 2 reasons

  1.  wants admin rights
  2.  I have set as a criterion that it should have at least   1 [CLASS:DirectUIHWND] and 1 [CLASS:SysTreeView32]

which does not meet


Thank you for the interaction, and for sharing your thoughts. :)

 

Edited by ioa747

I know that I know nothing

Posted (edited)

Thanks for the info. 
Because i'm running SrWare iron (which is a fork of chrome) in a sandbox, the script somehow does not recognize it.

So i thought to run the script inside the sandbox, and it works as intended.

Edited by Dan_555

Some of my script sourcecode

Posted

I updated to version 0.0.0.2
I changed the approach a bit and became more flexible with the criteria.
You don't need any more [CLASS:DirectUIHWND] and  [CLASS:SysTreeView32].
For now, you only need it to have a ToolbarWindow32 with a path
(the text box inside the toolbar should start with Address: )

and we see :)

I know that I know nothing

Posted

UpDate to version 0.0.0.3
I added the ability to catch a series of old-style dialogs
like Koda, Crimson Editor, IrfanView, etc.

I know that I know nothing

Posted
2 hours ago, argumentum said:

Haven't tried. But if you install to the "programs folder" you're supposed to have access to elevated windows.

I tried it but it doesn't work (at least in Windows 10)
It only works if I run it as administrator

I know that I know nothing

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...