Jump to content

Active_SaveFileDlg


ioa747
 Share

Recommended Posts

Add All open folder & some extra as contex menu in SaveFileDlg & OpenFileDlg of SciTE

Adds the ability to quickly select one of the open folders or one of those you use regularly.
as a destination to save the file
 
To test, open a few folders in the background and then select >File >Save As...  to SciTE

First add your favorite folders on line 58, 59,
you can put more, but above line 60 $OpenFolders[0][0] = UBound($OpenFolders) - 1
The number on the front  "002|D:\i\Pro\.AutoIT"  doesn't matter, but need to have it

Active_SaveFileDlg.png

 

Thanks to @Lepes suggestion for _WinApi_GetParent  function, so that only the SciTE dialogue is caught.

 

; https://www.autoitscript.com/forum/topic/210165-active_savefiledlg/
;----------------------------------------------------------------------------------------
; Title...........: Active_SaveFileDlg.au3
; Description.....: Add All open folder & some extra as contex menu in SaveFileDlg & OpenFileDlg of SciTE
; AutoIt Version..: 3.3.16.1   Author: ioa747
;----------------------------------------------------------------------------------------
#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7
;~ #NoTrayIcon
#include <WindowsConstants.au3>
#include <ButtonConstants.au3>
#include <WinAPISysWin.au3>
#include <Misc.au3>
#include <Array.au3>

Global $hGUI, $hDlgWnd, $hScite

If _Singleton(@ScriptName, 1) = 0 Then Exit ; to avoid running it multiple times!

While WinExists("[CLASS:SciTEWindow]")
    $hScite = WinGetHandle("[CLASS:SciTEWindow]")

    If WinExists("[TITLE:Save File; CLASS:#32770]") Then ; ------------ Save File
        $hDlgWnd = WinGetHandle("[TITLE:Save File; CLASS:#32770]")
        _CallFoldersGUI("Save")
    ElseIf WinExists("[TITLE:Open File; CLASS:#32770]") Then ; -------- Open File
        $hDlgWnd = WinGetHandle("[TITLE:Open File; CLASS:#32770]")
        _CallFoldersGUI("Open")
    EndIf

    Sleep(500)
WEnd

Exit
;----------------------------------------------------------------------------------------
Func _CallFoldersGUI($sDlgTitle)
    If _WinAPI_GetParent($hDlgWnd) = $hScite Then
        _FoldersGUI($sDlgTitle)
        While WinActive($hDlgWnd) ; Loop While win exits.
            Sleep(500)
        WEnd
        GUIDelete($hGUI)
    Else
        Return
    EndIf
EndFunc   ;==>_CallFoldersGUI
;----------------------------------------------------------------------------------------
Func _FoldersGUI($sDlgTitle)
    $hGUI = GUICreate("MyGUI", 40, 40, -50, -50, $WS_POPUP, BitOR($WS_EX_TOOLWINDOW, $WS_EX_NOACTIVATE), $hDlgWnd)
    Local $idDummy = GUICtrlCreateDummy()
    Local $idButton = GUICtrlCreateButton("contex button", 0, 0, 40, 40, $BS_ICON)
    GUICtrlSetImage(-1, "shell32.dll", -68)

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

    ; Add some extra folder (the numbers on the front don't matter)
    _ArrayInsert($OpenFolders, 1, "000|") ; separator
    _ArrayInsert($OpenFolders, 1, "001|D:\i\Pro\.AutoIT\_Test\005_Test") ; * <--------- Fav1 folder (get one of your own)
    _ArrayInsert($OpenFolders, 1, "002|D:\i\Pro\.AutoIT") ; * <------------------------ Fav2 folder (get one of your own)
    $OpenFolders[0][0] = UBound($OpenFolders) - 1

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

    Local $Wpos = WinGetPos($hDlgWnd)
    ;ConsoleWrite("$Wpos " & $Wpos[0] & "; " & $Wpos[1] & "; " & $Wpos[2] & "; " & $Wpos[3] & @CRLF)

    Local $aOfset[2]
    ;$aOfset[0]=X ;$aOfset[1]=Y
    If $sDlgTitle = "Save" Then
        $aOfset[0] = 270
        $aOfset[1] = 55
    ElseIf $sDlgTitle = "Open" Then
        $aOfset[0] = 270
        $aOfset[1] = 50
    EndIf

    GUISetState(@SW_SHOW, $hGUI)
    WinMove($hGUI, "", $Wpos[0] + $Wpos[2] - $aOfset[0], $Wpos[1] + $Wpos[3] - $aOfset[1])
    Local $idMsg

    While WinExists($hDlgWnd)

        $Wpos = WinGetPos($hDlgWnd)
        WinMove($hGUI, "", $Wpos[0] + $Wpos[2] - $aOfset[0], $Wpos[1] + $Wpos[3] - $aOfset[1])

        $idMsg = GUIGetMsg()
        Switch $idMsg
            Case 6 To $OpenFolders[0][0] + 6
                ;ConsoleWrite($OpenFolders[$idMsg - 5][1] & @CRLF)
                WinActivate($hDlgWnd)
                If $sDlgTitle = "Save" Then
                    ControlCommand($hDlgWnd, "", "ToolbarWindow324", "SendCommandID", 1280)
                    ControlSetText($hDlgWnd, "", "Edit2", $OpenFolders[$idMsg - 5][1])
                    ControlSend($hDlgWnd, "", "Edit2", "{ENTER}")
                ElseIf $sDlgTitle = "Open" Then
                    ControlCommand($hDlgWnd, "", "ToolbarWindow323", "SendCommandID", 1280)
                    ControlSetText($hDlgWnd, "", "Edit2", $OpenFolders[$idMsg - 5][1])
                    ControlSend($hDlgWnd, "", "Edit2", "{ENTER}")
                EndIf
            Case $idButton
                GUICtrlSendToDummy($idDummy)
            Case $idDummy
                MouseClick("right")
                ;ExitLoop
        EndSwitch

        Sleep(10)
    WEnd

    GUIDelete($hGUI)

    Return

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
;----------------------------------------------------------------------------------------

 

Edited by ioa747
only the SciTE dialogue is caught

I know that I know nothing

Link to comment
Share on other sites

UpDate the script

I changed the flow from

While 1
    $hWnd = WinWaitActive("[TITLE:Save File; CLASS:#32770]")
    _Main()
WEnd

to

While WinExists("[CLASS:SciTEWindow]")
    If WinExists("[TITLE:Save File; CLASS:#32770]") Then
        $hWnd = WinGetHandle("[TITLE:Save File; CLASS:#32770]")
        _Main()
    EndIf
    Sleep(500)
WEnd

to reduce processing power, because while the flow was waiting in WinWaitActive,  and I thought it is like pause, it used 0.48% processing power

 after the change it fell to 0.02%

and the  While WinExists("[CLASS:SciTEWindow]") , to terminate the script when the SciTE terminates

I know that I know nothing

Link to comment
Share on other sites

The way I made is using callbacks, Whenever an Open/ Save Dialog is started or ended by user, I got notified.
I didn't test eficiency because I have a longer script always running....

Let's say "It is the way I found", not sure if you like.

Local $hEventProc = DllCallbackRegister('_EventProc', 'none', 'ptr;dword;hwnd;long;long;dword;dword')

OnAutoItExitRegister('OnAutoItExit')
; Hook events detecting an Open/Save Dialog that is: open, closed, start moving/resizing so we close JFF and once moved/resized we launch again JFF.
Local $hEventHook = _WinAPI_SetWinEventHook($EVENT_SYSTEM_DIALOGSTART, $EVENT_SYSTEM_DIALOGEND, DllCallbackGetPtr($hEventProc))
Local $hEventHook_sized = _WinAPI_SetWinEventHook($EVENT_SYSTEM_MOVESIZESTART, $EVENT_SYSTEM_MOVESIZEEND, DllCallbackGetPtr($hEventProc))


Func OnAutoItExit()
        _WinAPI_UnhookWinEvent($hEventHook)
        _WinAPI_UnhookWinEvent($hEventHook_sized)
        DllCallbackFree($hEventProc)
EndFunc   ;==>OnAutoItExit

Func _EventProc($hEventHook, $iEvent, $hWnd, $iObjectID, $iChildID, $iThreadId, $iEventTime)
        #forceref $hEventHook, $iObjectID, $iChildID, $iThreadId, $iEventTime

        Switch $iEvent
                Case $EVENT_SYSTEM_DIALOGSTART
                    If WinActive("[Class:#32770]") Then ; Open standard Windows Dialog always exist, so check active!
                        $hOSDialog =  WinGetHandle("[ACTIVE]") ; Get the handle of this exact window
                        ; Bug: InputBox AutoIt function is a False Positive
                        If Not @error Then
                            If ControlGetHandle($hOSDialog, "", "[CLASS:Edit]" )Then
                                ConsoleWrite("Detected" & @CRLF)
                                LaunchJFF($hOSDialog)
                            EndIf
                        EndIf
                    EndIf

                Case $EVENT_SYSTEM_DIALOGEND
                        ConsoleWrite("close JFF " &@CRLF)
                        ConsoleWrite("WinClose return " & WinClose("Jumping From Folder To...") & @crlf)

                Case $EVENT_SYSTEM_MOVESIZESTART
                    ConsoleWrite("sizing start")
                    If $hWnd ==  $hOSDialog Then
                        ConsoleWrite( " winclose return " & WinClose("Jumping From Folder To...")& @CRLF)
                    EndIf
                Case $EVENT_SYSTEM_MOVESIZEEND
                    ConsoleWrite("sizing end")
                    If $hWnd ==  $hOSDialog Then
                        LaunchJFF($hOSDialog)
                    EndIf
        EndSwitch

EndFunc   ;==>_EventProc

We always need  "While 1 loop" to make alive our script so maybe it isn't worth these changes.

Edited by Lepes
Link to comment
Share on other sites

@Lepes  it's a good example to explore, since I am not familiar with it

However I couldn't catch $EVENT_SYSTEM_DIALOGSTART,  the rest is OK

and since it wasn't  ready to run , I had to reorganize it. So I don't know if I did something wrong

I'm attaching the test script, in case I made a mistake

; https://www.autoitscript.com/forum/topic/210165-active_savefiledlg/?do=findComment&comment=1517595
#include <WinAPISys.au3>

Global $hEventProc = DllCallbackRegister('_EventProc', 'none', 'ptr;dword;hwnd;long;long;dword;dword')
OnAutoItExitRegister('OnAutoItExit')
; Hook events detecting an Open/Save Dialog that is: open, closed, start moving/resizing so we close JFF and once moved/resized we launch again JFF.
Global $hEventHook = _WinAPI_SetWinEventHook($EVENT_SYSTEM_DIALOGSTART, $EVENT_SYSTEM_DIALOGEND, DllCallbackGetPtr($hEventProc))
Global $hEventHook_sized = _WinAPI_SetWinEventHook($EVENT_SYSTEM_MOVESIZESTART, $EVENT_SYSTEM_MOVESIZEEND, DllCallbackGetPtr($hEventProc))


While WinExists("[CLASS:SciTEWindow]")
    Sleep(500)
WEnd


Exit

;----------------------------------------------------------------------------------------
Func LaunchJFF($hOSDialog)
    ConsoleWrite("--- LaunchJFF -> $hOSDialog=" & $hOSDialog & @CRLF)
EndFunc   ;==>LaunchJFF
;----------------------------------------------------------------------------------------
Func OnAutoItExit()
    _WinAPI_UnhookWinEvent($hEventHook)
    _WinAPI_UnhookWinEvent($hEventHook_sized)
    DllCallbackFree($hEventProc)
EndFunc   ;==>OnAutoItExit
;----------------------------------------------------------------------------------------
Func _EventProc($hEventHook, $iEvent, $hWnd, $iObjectID, $iChildID, $iThreadId, $iEventTime)
    #forceref $hEventHook, $iObjectID, $iChildID, $iThreadId, $iEventTime

    Local $hOSDialog

    ConsoleWrite("-> ($hEventHook=" & $hEventHook)
    ConsoleWrite(", $iEvent=" & $iEvent)
    ConsoleWrite(", $hWnd=" & $hWnd)
    ConsoleWrite(", $iObjectID=" & $iObjectID)
    ConsoleWrite(", $iChildID=" & $iChildID)
    ConsoleWrite(", $iThreadId=" & $iThreadId)
    ConsoleWrite(", $iEventTime=" & $iEventTime & ") -> ")

    Switch $iEvent

        Case $EVENT_SYSTEM_DIALOGSTART
            ConsoleWrite("$EVENT_SYSTEM_DIALOGSTART" & @CRLF)
            If WinActive("[Class:#32770]") Then         ; Open standard Windows Dialog always exist, so check active!
                $hOSDialog = WinGetHandle("[ACTIVE]")          ; Get the handle of this exact window
                ; Bug: InputBox AutoIt function is a False Positive
                If Not @error Then
                    If ControlGetHandle($hOSDialog, "", "[CLASS:Edit]") Then
                        ConsoleWrite("Detected" & @CRLF)
                        LaunchJFF($hOSDialog)
                    EndIf
                EndIf
            EndIf

        Case $EVENT_SYSTEM_DIALOGEND
            ConsoleWrite("$EVENT_SYSTEM_DIALOGEND" & @CRLF)
            ConsoleWrite("WinClose return " & WinClose("Jumping From Folder To...") & @CRLF)

        Case $EVENT_SYSTEM_MOVESIZESTART
            ConsoleWrite("$EVENT_SYSTEM_MOVESIZESTART" & @CRLF)
            If $hWnd == $hOSDialog Then
                ConsoleWrite(" winclose return " & WinClose("Jumping From Folder To...") & @CRLF)
            EndIf
        Case $EVENT_SYSTEM_MOVESIZEEND
            ConsoleWrite("$EVENT_SYSTEM_MOVESIZEEND" & @CRLF)
            If $hWnd == $hOSDialog Then
                LaunchJFF($hOSDialog)
            EndIf

    EndSwitch

EndFunc   ;==>_EventProc

 

I know that I know nothing

Link to comment
Share on other sites

1 hour ago, ioa747 said:

@Lepes  it's a good example to explore, since I am not familiar with it

However I couldn't catch $EVENT_SYSTEM_DIALOGSTART,  the rest is OK

 

It works here:

- I run your script

- I use Notepad: File -> Open  (to show a standard Windows Open Dialog)  and I got on console Window:

>"D:\autoIt-v3\AutoIt3.exe" /ErrorStdOut "D:\lepes\ISN AutoIt Studio\Projects\00_inetFiles\messages.au3"    
-> ($hEventHook=0x00450625, $iEvent=16, $hWnd=0x000206A2, $iObjectID=0, $iChildID=0, $iThreadId=2308, $iEventTime=3366015) -> $EVENT_SYSTEM_DIALOGSTART
Detected
--- LaunchJFF -> $hOSDialog=0x000206A2

Did you solved?

Link to comment
Share on other sites

13 minutes ago, Lepes said:

- I use Notepad: File -> Open  (to show a standard Windows Open Dialog)  and I got on console Window:

👍 You are right, it works on the notepad, I only tried it on SciTE

what about the SciTE ?  :blink:

I know that I know nothing

Link to comment
Share on other sites

tested and works here too. If I try to open or save the file while the script is running, it is detected.

Keep in mind that Open / Save Dialogs are standard windows that are inside a Windows DLL. Notepad, Scite and many other program just call that window DLL to load and show these common dialogs. That's why all "Open File windows" on any program is the same window, because is part of Windows OS, it is not made neither by Notepad nor SciTe.

The Microsoft Windows common dialogs consist of the Open File, Save File, Open Folder, Find and Replace, Print, Page Setup, Font, and Color dialog boxes

Let me explain a Bug that maybe you didn't think about it. Using your actual program with this code:

While WinExists("[CLASS:SciTEWindow]")
    If WinExists("[TITLE:Save File; CLASS:#32770]") Then
        ConsoleWrite("scite window exists and Save Dialog is open")  ; Lepes
        $hWnd = WinGetHandle("[TITLE:Save File; CLASS:#32770]")
        _Main()
    EndIf
    Sleep(500)
WEnd

- Open SciTe, load your script and run it

- Open Notepad -> File -> Save As...

Your script will print on console "scite window exists and Save Dialog is open", because WinExists detected SciTE window on the background, the second "if" will be true because the title is "Save File" and the class is 32770 because it is a common Windows OS Dialog.

So, You are not detecting "Save File" inside SciTE. You are detecting "Save File Dialog" globally to Windows OS. The same happens using my code.

If you only want your custom button inside SciTe, you need a different approach, for example getting the parent window of the "Save Dialog" this will tell you the application that called this Dialog. I modified your code and tested, I marked lines I have modified with "//Lepes"

; https://www.autoitscript.com/forum/topic/210165-active_savefiledlg/#comment-1517621
; https://www.autoitscript.com/forum/topic/210165-active_savefiledlg/
;----------------------------------------------------------------------------------------
; Title...........: Active_SaveFileDlg.au3
; Description.....: Add All open folder & some extra as contex menu in SaveFileDlg & OpenFileDlg of SciTE
; AutoIt Version..: 3.3.16.1   Author: ioa747
;----------------------------------------------------------------------------------------
#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7
;~ #NoTrayIcon
#include <Misc.au3>
#include <WindowsConstants.au3>
#include <ButtonConstants.au3>
#include <Array.au3>
#include <WinAPISysWin.au3>  ; _WinApi_GetParent  //Lepes

Global $hGUI, $hDlgWnd, $hScite

If _Singleton(@ScriptName, 1) = 0 Then Exit ; to avoid running it multiple times!

While WinExists("[CLASS:SciTEWindow]")
    $hScite = WinGetHandle("[CLASS:SciTEWindow]")   ; save this handle   //Lepes
    If WinExists("[TITLE:Save File; CLASS:#32770]") Then ; ------------ Save File
        $hDlgWnd = WinGetHandle("[TITLE:Save File; CLASS:#32770]")
        If _WinApi_GetParent($hDlgWnd) == $hScite Then   ; SciTE called the Save Dialog //Lepes
            ConsoleWrite(" parent of Save Dialog is scite" & @CRLF)  ; //Lepes
            _CallFoldersGUI("Save")
        Else
            ConsoleWrite("parent of Save File Dialog is not scite" & @CRLF) ;  //Lepes
        EndIf
    ElseIf WinExists("[TITLE:Open File; CLASS:#32770]") Then ; -------- Open File
        $hDlgWnd = WinGetHandle("[TITLE:Open File; CLASS:#32770]")
        _CallFoldersGUI("Open")
    EndIf

    Sleep(500)
WEnd

Exit
;----------------------------------------------------------------------------------------
Func _CallFoldersGUI($sDlgTitle)

    _FoldersGUI($sDlgTitle)

    While WinActive($hDlgWnd) ; Loop While win exits.
        Sleep(500)
    WEnd

    GUIDelete($hGUI)

EndFunc   ;==>_CallFoldersGUI
;----------------------------------------------------------------------------------------
Func _FoldersGUI($sDlgTitle)

    $hGUI = GUICreate("MyGUI", 40, 40, -1, -1, $WS_POPUP, BitOR($WS_EX_TOOLWINDOW, $WS_EX_NOACTIVATE), $hDlgWnd)
    Local $idDummy = GUICtrlCreateDummy()
    Local $idButton = GUICtrlCreateButton("contex button", 0, 0, 40, 40, $BS_ICON)
    GUICtrlSetImage(-1, "shell32.dll", -68)

    Local $idContext = GUICtrlCreateContextMenu($idButton)

    Local $OpenFolders = _EnumAllOpenFolder()

    ; Add some extra folder (the numbers on the front don't matter)
    _ArrayInsert($OpenFolders, 1, "000|") ; separator
    _ArrayInsert($OpenFolders, 1, "001|D:\i\Pro\.AutoIT\_Test\005_Test") ; * <--------- Fav1 folder (get one of your own)
    _ArrayInsert($OpenFolders, 1, "002|D:\i\Pro\.AutoIT") ; * <------------------------ Fav2 folder (get one of your own)
    $OpenFolders[0][0] = UBound($OpenFolders) - 1

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

    GUISetState(@SW_SHOW, $hGUI)

    Local $Wpos = WinGetPos($hDlgWnd)
    ;ConsoleWrite("$Wpos " & $Wpos[0] & "; " & $Wpos[1] & "; " & $Wpos[2] & "; " & $Wpos[3] & @CRLF)

    Local $idMsg

    While WinExists($hDlgWnd)

        $Wpos = WinGetPos($hDlgWnd)

        Local $aOfset[2]
        ;$aOfset[0]=X ;$aOfset[1]=Y
        If $sDlgTitle = "Save" Then
            $aOfset[0] = 270
            $aOfset[1] = 55
        ElseIf $sDlgTitle = "Open" Then
            $aOfset[0] = 270
            $aOfset[1] = 50
        EndIf

        WinMove($hGUI, "", $Wpos[0] + $Wpos[2] - $aOfset[0], $Wpos[1] + $Wpos[3] - $aOfset[1])

        $idMsg = GUIGetMsg()
        Switch $idMsg
            Case 6 To $OpenFolders[0][0] + 6
                ;ConsoleWrite($OpenFolders[$idMsg - 5][1] & @CRLF)
                WinActivate($hDlgWnd)
                If $sDlgTitle = "Save" Then
                    ControlCommand($hDlgWnd, "", "ToolbarWindow324", "SendCommandID", 1280)
                    ControlSetText($hDlgWnd, "", "Edit2", $OpenFolders[$idMsg - 5][1])
                    ControlSend($hDlgWnd, "", "Edit2", "{ENTER}")
                ElseIf $sDlgTitle = "Open" Then
                    ControlCommand($hDlgWnd, "", "ToolbarWindow323", "SendCommandID", 1280)
                    ControlSetText($hDlgWnd, "", "Edit2", $OpenFolders[$idMsg - 5][1])
                    ControlSend($hDlgWnd, "", "Edit2", "{ENTER}")
                EndIf

            Case $idButton
                GUICtrlSendToDummy($idDummy)
            Case $idDummy
                MouseClick("right")
                ;ExitLoop

        EndSwitch

        Sleep(10)
    WEnd

    GUIDelete($hGUI)

    Return

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
;----------------------------------------------------------------------------------------

 

Using Hooks it is the same, you need to check the parent:

; https://www.autoitscript.com/forum/topic/210165-active_savefiledlg/#comment-1517621
; https://www.autoitscript.com/forum/topic/210165-active_savefiledlg/?do=findComment&comment=1517595
#include <WinAPISys.au3>

Global $hEventProc = DllCallbackRegister('_EventProc', 'none', 'ptr;dword;hwnd;long;long;dword;dword')
OnAutoItExitRegister('OnAutoItExit')
; Hook events detecting an Open/Save Dialog that is: open, closed, start moving/resizing so we close JFF and once moved/resized we launch again JFF.
Global $hEventHook = _WinAPI_SetWinEventHook($EVENT_SYSTEM_DIALOGSTART, $EVENT_SYSTEM_DIALOGEND, DllCallbackGetPtr($hEventProc))
Global $hEventHook_sized = _WinAPI_SetWinEventHook($EVENT_SYSTEM_MOVESIZESTART, $EVENT_SYSTEM_MOVESIZEEND, DllCallbackGetPtr($hEventProc))


While WinExists("[CLASS:SciTEWindow]")
    Sleep(500)
WEnd


Exit

;----------------------------------------------------------------------------------------
Func LaunchJFF($hOSDialog)
    ConsoleWrite("--- LaunchJFF -> $hOSDialog=" & $hOSDialog & @CRLF)
EndFunc   ;==>LaunchJFF
;----------------------------------------------------------------------------------------
Func OnAutoItExit()
    _WinAPI_UnhookWinEvent($hEventHook)
    _WinAPI_UnhookWinEvent($hEventHook_sized)
    DllCallbackFree($hEventProc)
EndFunc   ;==>OnAutoItExit
;----------------------------------------------------------------------------------------
Func _EventProc($hEventHook, $iEvent, $hWnd, $iObjectID, $iChildID, $iThreadId, $iEventTime)
    #forceref $hEventHook, $iObjectID, $iChildID, $iThreadId, $iEventTime

    Local $hOSDialog

    ConsoleWrite("-> ($hEventHook=" & $hEventHook)
    ConsoleWrite(", $iEvent=" & $iEvent)
    ConsoleWrite(", $hWnd=" & $hWnd)
    ConsoleWrite(", $iObjectID=" & $iObjectID)
    ConsoleWrite(", $iChildID=" & $iChildID)
    ConsoleWrite(", $iThreadId=" & $iThreadId)
    ConsoleWrite(", $iEventTime=" & $iEventTime & ") -> ")

    Switch $iEvent

        Case $EVENT_SYSTEM_DIALOGSTART
            ConsoleWrite("$EVENT_SYSTEM_DIALOGSTART" & @CRLF)
            If WinActive("[Class:#32770]") Then         ; Open standard Windows Dialog always exist, so check active!
                $hOSDialog = WinGetHandle("[ACTIVE]")          ; Get the handle of this exact window
                ; Bug: InputBox AutoIt function is a False Positive
                If Not @error Then
                    If ControlGetHandle($hOSDialog, "", "[CLASS:Edit]") Then
                        local $hParentOSDialog = _WinApi_GetParent($hOsDialog)          ; //Lepes
                        If WinExists("[CLASS:SciTEWindow]") Then                        ; //Lepes
                            $hScite = WinGetHandle("[CLASS:SciTEWindow]")               ; //Lepes
                            If $hScite == $hParentOSDialog Then                         ; //Lepes
                                ConsoleWrite("Detected  Dialog inside scite" & @CRLF)   ; //Lepes
                                LaunchJFF($hOSDialog)
                            Else
                                ConsoleWrite("Detected Dialog FROM ANOTHER PROGRAM, is not scite" & @CRLF)  ; //Lepes
                            EndIf
                        EndIf
                    EndIf
                EndIf
            EndIf

        Case $EVENT_SYSTEM_DIALOGEND
            ConsoleWrite("$EVENT_SYSTEM_DIALOGEND" & @CRLF)
            ConsoleWrite("WinClose return " & WinClose("Jumping From Folder To...") & @CRLF)

        Case $EVENT_SYSTEM_MOVESIZESTART
            ConsoleWrite("$EVENT_SYSTEM_MOVESIZESTART" & @CRLF)
            If $hWnd == $hOSDialog Then
                ConsoleWrite(" winclose return " & WinClose("Jumping From Folder To...") & @CRLF)
            EndIf
        Case $EVENT_SYSTEM_MOVESIZEEND
            ConsoleWrite("$EVENT_SYSTEM_MOVESIZEEND" & @CRLF)
            If $hWnd == $hOSDialog Then
                LaunchJFF($hOSDialog)
            EndIf

    EndSwitch

EndFunc   ;==>_EventProc

Hope this help.

 

Link to comment
Share on other sites

@Lepes 👍 The explanation is excellent !
Thanks a lot for the analysis. I have already adopted the _WinApi_GetParent  function, so that only the SciTE dialogue is caught.

Using Hooks case:
I couldn't catch $EVENT_SYSTEM_DIALOGSTART from SciTE

The last script titled Using Hooks it is the same, you need to check the parent:  , have you tried it and it works for SciTE ?


It doesn't give me anything in the console when I open the save dialog, but if I close it or move it it gives me

maybe you can draw some conclusion  dlgTest.xls

Edited by ioa747

I know that I know nothing

Link to comment
Share on other sites

Yes I tried and it works with GetParent and Without GetParent. I'm using Win 8.1 64 bits, not sure if it is something related to that.

2023_05_05__11_57_05_159.thumb.png.f928644ff2719f5462e75ddab95f5b01.png

In fact SciTE about box is detected as a "Dialog start" too

2023_05_05__12_12_13_227.thumb.png.7bd5978e4bab52c3d11cc4923a06c966.png

In this case there is no "Detected" message because the dialog contol doesn't have an Edit control, it is a Scintilla control.

The latest test: Open Dialog from Notepad:

2023_05_05__12_24_22_329.thumb.png.54de3aa4cf936c25c7b8d44c3e0bb8a4.png

At this point I don't know what is happening in your computer. Maybe I'm doing something wrong and I don't even know🤔 

Link to comment
Share on other sites

Global $sIsOpenOrSave = "", $iCount = 0
While WinExists("[CLASS:SciTEWindow]")
    $hScite = WinGetHandle("[CLASS:SciTEWindow]")
    $hDlgWnd = ControlGetHandle ("[CLASS:#32770]", "", "ToolbarWindow323")
    If $hDlgWnd Then
        If ControlGetHandle( "[CLASS:#32770]", "", "ToolbarWindow325") Then
            $sIsOpenOrSave = "Save"
        Else
            $sIsOpenOrSave = "Open"
        EndIf
        $iCount = 0 ;;; https://www.autoitscript.com/forum/topic/210165-active_savefiledlg/?do=findComment&comment=1517896
        While 1
            $hDlgWnd = _WinAPI_GetParent($hDlgWnd)
            ;ConsoleWrite($hDlgWnd & @TAB &  WinGetTitle($hDlgWnd) & @TAB & WinGetHandle("[CLASS:#32770]") &  @CRLF)
            $iCount += 1
            If $iCount = ( $sIsOpenOrSave = "Open" ? 6 : 4 ) Then ExitLoop
        WEnd
        _CallFoldersGUI($sIsOpenOrSave)
    EndIf
    Sleep(500)
WEnd

language is no longer important this way :) 

..should check if the next parent is SciTE to make sure this code is not running on an unexpected window, but as is, is good enough to show the idea.

Edited by argumentum
better code

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

It's interesting... I always get:

open:        [CLASS:ToolbarWindow32; INSTANCE:3]
Save:         [CLASS:ToolbarWindow32; INSTANCE:4]  not 5, I don't know why. Tested on Notepad++, PrusaSlicer, SciTe, Paint

Edited by Lepes
Link to comment
Share on other sites

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
 Share

×
×
  • Create New...