Jump to content

Explorer Session Saver


JohnBailey
 Share

Recommended Posts

Description - Allows you to save explorer windows and load them in their saved state at a later time. This is very helpful for those who want folders setup on their desktop in a particular manner.

Instructions - Simply run the exe and it will appear in your systray. From there you are able to right-click and perform the saving, loading, and other actions..

Current Version: 1.3.0

Version History:

1.0.0 - Initial Release

1.1.0 - Fix: Minimized or Maximized windows will restore properly

Add: Remembers Minimized or Maximized state of a window

Fix: If window saved is already opened, then the window is activated

Note: This resolves the endless loop issue

1.2.0 - Add: Advanced options in sysIcon

1.2.1 - Fix: Folderview, if not visible/closed, does not open reopen in loaded session

1.3.0 - Add: Remembers the Listview item text color, background color, background img, background img mode

Note: the background img mode edit must be a manual change in ess file (see tutorials for how to do this)

Add: Remembers Column Sort (which column was used to sort)

Note: Currently is limited to 4 columns. For more, please make a request

To-Do Ideas:

- Speedup loading session

- Remember History, Favorites, and Search BrowserBar.

- Remember Column Width

- Prevent New Explorer Window from stealing focus.

- Remember Group View

- Image ability for column headers

- Settings (eg. allowing the user to choose what features are enabled)

Script

#AutoIt3Wrapper_icon=Desktop.ico
; http://www.iconarchive.com/download/ico/mayosoft/azullustre-2/Desktop.ico

;=============================================================================
; Version History:
;           1.0.0 - Initial Release
;           1.1.0 - Fix: Minimized or Maximized windows will restore properly
;                   Add: Remembers Minimized or Maximized state of a window
;                   Fix: If window saved is already opened, then the window is activated 
;                           This resolves the endless loop issue
;           1.2.0 - Add: Advanced options in sysIcon
;           1.2.1 - Fix: Folderview, if not visible/closed, does not open reopen in loaded session
;           1.3.0 - Add: Remembers the Listview item text color, background color, background img, background img mode
;                       Note: the background img mode edit must be a manual change in ess file
;                   Add: Remembers Column Sort (which column was used to sort)
;                       Note: Currently is limited to 4 columns. For more, please make a request
;
; To-Do List Ideas:
;           0. Speedup loading session
;           1. Remember History, Favorites, and Search BrowserBar.
;           2. Remember Column Width
;           3. Prevent New Explorer Window from stealing focus.
;           4. Remember Group View
;           5. Image ability for column headers
;           6. Settings (eg. allowing the user to choose what features are enabled)
;
; Thanks: 
;   Dale Hohm
;   Gary Frost
;
;=============================================================================
Global $version = '1.3.0'
#Include <GuiListView.au3>
#Include <GuiHeader.au3>
#Include <File.au3>
#Include <Array.au3>

Opt("TrayMenuMode", 1)
Opt("TrayOnEventMode",1)
Opt("OnExitFunc", "OnAutoItExit"); Used for further features and diagnosis
Opt("GUIOnEventMode", 1)


;HotKeySet('{ESC}','Terminate');Used during Testing

; IShellDispatch2 (http://msdn2.microsoft.com/en-us/library/bb774150.aspx) 
; Thank you Dale Hohm
Global Const $ExplorerBarCLSID_Folders   = '{EFA24E64-B078-11d0-89E4-00C04FC9E26E}'
Global Const $ExplorerBarCLSID_History   = '{EFA24E62-B078-11d0-89E4-00C04FC9E26E}'
Global Const $ExplorerBarCLSID_Favorites = '{EFA24E61-B078-11d0-89E4-00C04FC9E26E}'
Global Const $ExplorerBarCLSID_Search    = '{30D02401-6A81-11d0-8274-00C04FD5AE38}'

Global $columns = 16

TraySetToolTip("Explorer Session Saver v"&$version&" - Save and Load MS Explorer Windows with the positions and settings")
TraySetClick(16)
$MenuItem3 = TrayCreateItem("Exit")
TrayItemSetOnEvent($MenuItem3, "MenuItem3Click")
TrayCreateItem("")
$MenuItem6 = TrayCreateMenu("Control All")
TrayItemSetOnEvent($MenuItem6, "MenuItem6Click")
$MenuItem7 = TrayCreateItem("Close All",$MenuItem6)
TrayItemSetOnEvent($MenuItem7, "MenuItem7Click")
TrayCreateItem("")
$MenuItem2 = TrayCreateItem("Load Session")
TrayItemSetOnEvent($MenuItem2, "MenuItem2Click")
$MenuItem1 = TrayCreateItem("Save Session")
TrayItemSetOnEvent($MenuItem1, "MenuItem1Click")
TrayCreateItem("")
$MenuItem4 = TrayCreateItem("Quick Load")
TrayItemSetOnEvent($MenuItem4, "MenuItem4Click")
$MenuItem5 = TrayCreateItem("Quick Save")
TrayItemSetOnEvent($MenuItem5, "MenuItem5Click")

While 1
    Sleep(100)
WEnd

Func SaveSession($_dialog=True)
    Local $winArray[1][$columns+1]
    
    If $_dialog Then
        Local $_file = FileSaveDialog('Where to Save',@MyDocumentsDir,"Explorer Session File (*.esf)",16,'Explorer Session - '&@MON&@MDAY&@YEAR)
        If @error Then
            Return 0
        EndIf
        If StringRight($_file,4) <> '.esf' Then
            $_file &= '.esf'
        EndIf
    Else
        Local $_file = @MyDocumentsDir&'\Previous Session.esf'
    EndIf
    _FileCreate($_file)
    $oShell = ObjCreate("shell.application")   ; Get the Windows Shell Object
    $oShellWindows=$oShell.windows       ; Get the collection of open shell Windows
    Local $count = 0
    If Isobj($oShellWindows) Then
        For $Window In $oShellWindows       ; Count all existing shell windows
            
            Local $WindowHwnd = HWnd($window.HWnd())
            Local $winLocation = StringReplace($window.locationURL (),'%20',' ')
            Local $winName = $window.LocationName
            
            ConsoleWrite('WinName: '&$winName &@CRLF)
            
            Local $FileListView_HWnd=ControlGetHandle($WindowHwnd,'','[Class:SysListView32;Instance:1]')
            
            Local $HeaderControlHandle = ControlGetHandle($WindowHwnd ,'','SysHeader321');[class:SysHeader32;instance:1]
            Local $colCount = _GUICtrlListView_GetColumnCount($FileListView_HWnd)
            Local $columnToSort = 0
            Local $columnSortType = 0
            Local $columnSortDirection = 0 
            Local $columnFlag
            For $_c = 0 To $colCount-1
                Local $_colflag = _GUICtrlHeader_GetItemFlags($HeaderControlHandle, $_c)
                If $_colflag <> 0 Then
                    Switch $_colflag 
                    Case 4,8
                        $columnToSort = $_c
                        $columnFlag = $_colflag                 
                        If $columnFlag = 8 Then;up arrow (default = up/descending)
                            ConsoleWrite('   Col '& $_c &' - Item Flag: '&$_colflag &@CRLF)
                            ConsoleWrite('  Col Sort Type: '&'descending' &@CRLF)
                            $columnSortDirection = 1;Descending
                        ElseIf $columnFlag = 4 Then;down arrow
                            ConsoleWrite('   Col '& $_c &' - Item Flag: '&$_colflag &@CRLF)
                            ConsoleWrite('  Col Sort Type: '& 'ascending' &@CRLF)
                            $columnSortDirection = 0;Ascending
                        EndIf
                    Case Else
                        
                    EndSwitch
                EndIf
            Next
            
            Local $WinStateTotal = WinGetState($WindowHwnd)
            If BitAND($WinStateTotal,16) Then
                $window.visible=0
;~              WinSetState($WindowHwnd,'',@SW_HIDE)
                WinSetState($WindowHwnd,'',@SW_RESTORE)
                Local $winPos = WinGetPos($WindowHwnd)
                WinSetState($WindowHwnd,'',@SW_MINIMIZE)
;~              WinSetState($WindowHwnd,'',@SW_SHOW)
                
                Local $WinState = 'MINIMIZE'
            ElseIf BitAND($WinStateTotal,32) Then
;~              WinSetState($WindowHwnd,'',@SW_HIDE)
                WinSetState($WindowHwnd,'',@SW_RESTORE)
                Local $winPos = WinGetPos($WindowHwnd)
                WinSetState($WindowHwnd,'',@SW_MAXIMIZE)
;~              WinSetState($WindowHwnd,'',@SW_SHOW)
                
                
                Local $WinState  = 'MAXIMIZE'
            Else
                Local $winPos = WinGetPos($WindowHwnd)
                
                Local $WinState  = 'RESTORE'
            EndIf
            
            Local $x = $winPos[0];$window.Left ()
            Local $y = $winPos[1];$window.Top ()
            Local $w = $winPos[2];$window.Width ()
            Local $h = $winPos[3];$window.Height ()

            
            Local $vis = $window.Visible()
            Local $FolderBarState
            Local $BrowserBar_HWnd=ControlGetHandle($WindowHwnd,'','[Class:SysTreeView32;Instance:1]')
            If $BrowserBar_HWnd <> 0 Then
                Local $lvPosArray = ControlGetPos($WindowHwnd,'',$FileListView_HWnd)
                If $lvPosArray[0] <> 0 Then
                    $FolderBarState = 1
                Else
                    $FolderBarState = 0
                EndIf
            Else
                $FolderBarState = 0
            EndIf
            
            If $vis = -1 Then
                $vis = 1
            Else
                $vis = 0
            EndIf
            If StringInStr($winLocation,'file://') Then;prevents from Internet Explorer windows being captured
                $count += 1
                Redim $winArray[UBound($winArray)+1][UBound($winArray,2)]
                $winArray[UBound($winArray)-1][0] = $WindowHwnd
                $winArray[UBound($winArray)-1][1] = $winName
                $winArray[UBound($winArray)-1][2] = $winLocation
                $winArray[UBound($winArray)-1][3] = $x
                $winArray[UBound($winArray)-1][4] = $y
                $winArray[UBound($winArray)-1][5] = $w
                $winArray[UBound($winArray)-1][6] = $h
                $winArray[UBound($winArray)-1][7] = $vis; Currently not used, but could be used in the future
                $winArray[UBound($winArray)-1][8] = $WinState
                $winArray[UBound($winArray)-1][9] = $FolderBarState
                $winArray[UBound($winArray)-1][10] = _GUICtrlListView_GetView($FileListView_HWnd)
                $winCurrentBKImage = _GUICtrlListView_GetBkImage($FileListView_HWnd)
;~              _ArrayDisplay($winCurrentBKImage)
                Switch $winCurrentBKImage[0]
                    Case 0
                    ConsoleWrite("Background: img not there"&@CRLF)
                    $winArray[UBound($winArray)-1][11] = 'img'
                    Case Else
                    ConsoleWrite("Background: "& $winCurrentBKImage[1] &@CRLF)
                    $winArray[UBound($winArray)-1][11] = $winCurrentBKImage[1]
                EndSwitch
                $winArray[UBound($winArray)-1][12] = '0'; img mode (1 = tile, 0 = regular)
                $winArray[UBound($winArray)-1][13] = _GUICtrlListView_GetBkColor($FileListView_HWnd);
                $winArray[UBound($winArray)-1][14] = _GUICtrlListView_GetTextColor($FileListView_HWnd);'textcolor'
                $winArray[UBound($winArray)-1][15] = $columnToSort; Column To Sort
                $winArray[UBound($winArray)-1][16] = $columnFlag; 4 = Ascending, 8 = Descending
                
;~              _ArrayDisplay($winArray)
                
            ; == Write To the file ==;
                Local $lineToWrite = ''
                For $_b = 1 To UBound($winArray,2)-1
                    If $_b <> UBound($winArray,2)-1 Then
                        $lineToWrite &= $winArray[UBound($winArray)-1][$_b]&chr(134)
                    Else;Last Column Entry so no delimiter is required
                        $lineToWrite &= $winArray[UBound($winArray)-1][$_b]
                    EndIf
                Next
                _FileWriteToLine($_file,$count,$lineToWrite,1)
                If @error Then
                    TrayTip('Explorer Session Saver - Error','Could not write line '&$count&' to file '&$_file&' (extended: '&@error&')',2)
                EndIf
            ; ========================;
                
            EndIf
            
        Next
    Else
        TrayTip('Explorer Session Saver - Error','Shell.Application.Windows object problem unknown',2)
    EndIf
    $winArray = 0;Reset Array
EndFunc
Func LoadSession($_Dialog=True)
    If $_dialog Then
        Local $_file = FileOpenDialog('Where to Save',@MyDocumentsDir,"Explorer Session File (*.esf)",2)
        If @error Then
            Return 0
        EndIf
        If StringRight($_file,4) <> '.esf' Then
            $_file &= '.esf'
        EndIf
    Else
        Local $_file = @MyDocumentsDir&'\Previous Session.esf'
        If Not FileExists($_file) Then
            TrayTip('Explorer Session Saver - Error','Quick Save File cannot be located: '&$_file,3)
            Return -1
        EndIf
    EndIf
    Local $oShell = ObjCreate("shell.application")   ; Get the Windows Shell Object
    Local $oShellWindows = $oShell.windows
    If NOT Isobj($oShellWindows) Then
        TrayTip('Explorer Session Saver - Error','Shell.Application.Windows object problem unknown',3)
        Return -1
    EndIf
    Local $currentTotal = $oShell.windows.count
    
    Local $PreviousBound = $currentTotal-1
    
    Local $_fileArray
    _FileReadToArray($_file,$_fileArray)
    ProgressOn('Explorer Session Saver','Loading Session')
;============================================================
;= Lock Windows                     
        
;============================================================
    Local $totalToLoad = 0
    For $_a = 1 To UBound($_fileArray)-1
        Local $_lineSplit = StringSplit($_fileArray[$_a],Chr(134),1)
        If $_lineSplit[0] <> $columns Then
            ContinueLoop
        Else
            $totalToLoad += 1
        EndIf
        
    Next
    
    For $_a = 1 To UBound($_fileArray)-1
        Local $_lineSplit = StringSplit($_fileArray[$_a],Chr(134),1)
        Local $percent = $_a * (100/$totalToLoad)
        ProgressSet($percent,$_a&' of '&$totalToLoad&'     Please Wait')
        If $_lineSplit[0] <> $columns Then
            ContinueLoop
        EndIf
        
        Local $winName = $_lineSplit[1]
        Local $winLocation = $_lineSplit[2]
        Local $x = $_lineSplit[3]
        Local $y = $_lineSplit[4]
        Local $w = $_lineSplit[5]
        Local $h = $_lineSplit[6]
        Local $vis = $_lineSplit[7]
        Local $WinState = $_lineSplit[8]
        Local $FolderBarState = $_lineSplit[9]
        Local $LV_View = $_lineSplit[10]
        Local $LV_BackgroundImg = $_lineSplit[11]
        Local $LV_BackgroundImg_Tile = $_lineSplit[12]
        Local $LV_BackgroundColor = $_lineSplit[13]
        Local $LV_TextColor = $_lineSplit[14]
        Local $columnToSort = $_lineSplit[15]
        Local $columnFlag = $_lineSplit[16] 
        
        If StringInStr($winLocation,'///') Then
            Local $_locationTrimed = StringReplace($winLocation,'file:///','')
        Else
            Local $_locationTrimed = StringReplace($winLocation,'file:','')
        EndIf
        DirGetSize($_locationTrimed)
        If @error Then
            TrayTip('Explorer Session Saver','Folder No Longer Exists: '&$_locationTrimed,3)
            ContinueLoop
        EndIf
        Local $foundWin = 0
        For $_b= 0 To $currentTotal-1;Check if it's already open
            Local $Window = $oShell.windows.item($_b)
            Local $_storedLocation = StringReplace($window.locationURL(),'%20',' ')
;~          TrayTip('Explorer Session Saver','Checking Window '&$_storedLocation& ' for '&$winLocation,3)
            If $_storedLocation = $winLocation Then
                $foundWin = 1;----NOTE----:  Instead of doing the skip method, you could do an open new window (eg. C:\) and then nav that to the storedLocation
                TrayTip('Explorer Session Saver','Location '&$_locationTrimed &' already opened.',3)
            EndIf
        Next
        If $foundWin = 1 Then;----NOTE----:  Instead of doing the skip method, you could do an open new window (eg. C:\) and then nav that to the storedLocation
            ContinueLoop
        EndIf
        $oShell.open($winLocation)
        $PreviousBound +=1
        Local $_Timer = TimerInit()
        Local $_timeout = 6000
        While 1
            Local $currentTotal = $oShell.windows.count
;~          ConsoleWrite('$currentTotal: '&$currentTotal & ' vs '&($PreviousBound+1)&@LF)
            If  $currentTotal = ($PreviousBound+1) Then
                ExitLoop
            EndIf
            If TimerDiff($_Timer) > $_timeout Then
                $foundWin = 1
                TrayTip('Explorer Session Saver','Location '&$_locationTrimed &' could not open. Timed-out',3)
                ExitLoop
            EndIf
            Sleep(100)
        WEnd
        
        Local $Window = $oShell.windows.item($PreviousBound)
        Local $WindowHwnd = HWnd($window.HWnd())
        
        If $WinState = 'MINIMIZE' Then
            WinSetState($WindowHwnd,'',@SW_MINIMIZE)
        ElseIf $WinState = 'MINIMIZE' Then
            WinSetState($WindowHwnd,'',@SW_MAXIMIZE)
        EndIf
        
        Local $FileListView_HWnd=ControlGetHandle($WindowHwnd,'','[Class:SysListView32;Instance:1]')
        
        If $FolderBarState = 1 Then
            $window.ShowBrowserBar ($ExplorerBarCLSID_Folders, True)
        EndIf
        
        _GUICtrlListView_SetView($FileListView_HWnd,$LV_View)
        
        If $LV_TextColor <> 'textcolor' Then
            _GUICtrlListView_SetTextColor ($FileListView_HWnd, $LV_TextColor)
        EndIf
        
        If $LV_BackgroundImg <> 'img' Then
            If FileExists( $LV_BackgroundImg ) Then
                _GUICtrlListView_SetBkImage ($FileListView_HWnd, $LV_BackgroundImg, $LV_BackgroundImg_Tile)
            EndIf
        EndIf
        
        If $LV_BackgroundColor <> 'bkcolor' Then
            _GUICtrlListView_SetBkColor($FileListView_HWnd, $LV_BackgroundColor)
            _GUICtrlListView_SetTextBkColor ($FileListView_HWnd, $LV_BackgroundColor)
        EndIf
        
        Local $HeaderControlHandle = ControlGetHandle($WindowHwnd ,'','SysHeader321');[class:SysHeader32;instance:1]
        Local $colCount = _GUICtrlListView_GetColumnCount($FileListView_HWnd)
        If $colCount > 0 Then
            
            Local $columnWidths[ $colCount ]
            
            
            
            Local $runningPos = 1
            For $_c = 0 to UBound($columnWidths)-1
                If $_c = 0 Then
                    $columnWidths[$_c] = 1
                Else
                $runningPos += _GUICtrlListView_GetColumnWidth($FileListView_HWnd, $_c-1)+2;_GUICtrlHeader_GetItemWidth($HeaderControlHandle, $_c-1) + 2
                $columnWidths[$_c] = $runningPos
                EndIf
            Next

;~          If $columnSortDirection = 0 Then
;~              $B_DESCENDING[$columnToSort] = 'False'
;~          ElseIf $columnSortDirection = 1 Then
;~              $B_DESCENDING[$columnToSort] = 'True'
;~          EndIf

        ; Capture Columns Positions
            Local $lvPosArray = ControlGetPos($WindowHwnd,'',$FileListView_HWnd)

            Local $columnToSort = 0
            Local $columnSortType = 0
            Local $_colflag = _GUICtrlHeader_GetItemFlags($HeaderControlHandle, $columnToSort)
            Switch $_colflag 
            Case 4,8
                If $columnFlag <> $_colflag Then
                    ControlClick ($WindowHwnd, "", $HeaderControlHandle ,'left' ,1 ,Number($columnWidths[$columnToSort])+5,1 )
                EndIf
            EndSwitch
            
;~          For $_c = 0 to $colCount-1
;~              If $columnToSort <> $_c Then
;~                  _GUICtrlHeader_SetItemFormat ($HeaderControlHandle, $_c, BitOR($HDF_LEFT, $HDF_STRING))
;~              EndIf
;~          Next
        EndIf
        
        ControlSend($WindowHwnd,'',$FileListView_HWnd,"{F5}");Refresh (this is for the item color adjustments
        WinMove($WindowHwnd,'',$x,$y,$w,$h)
    Next
    
    ProgressOff()
EndFunc

Func ExplorerControl_AllOpen($_flag)
    If $_flag = 1 Then;Close All Open
        Local $oShell = ObjCreate("shell.application")   ; Get the Windows Shell Object
        Local $oShellWindows = $oShell.windows
        Local $currentTotal = $oShell.windows.count
        For $_i = $currentTotal-1 to 0 Step -1
            Local $Window = $oShell.windows.item($_i)
            Local $winLocation = StringReplace($window.locationURL (),'%20',' ')
            If StringInStr($winLocation,'file://') Then
                $window.quit
            EndIf
        Next
    EndIf
EndFunc

Func MenuItem1Click() 
    SaveSession()
EndFunc
Func MenuItem2Click()
    LoadSession()
EndFunc
Func MenuItem3Click();Exit
    Terminate()
EndFunc
Func MenuItem4Click()
    LoadSession(False)
EndFunc
Func MenuItem5Click(); Quick Save
    SaveSession(False)
EndFunc

Func MenuItem6Click(); 
    
EndFunc
Func MenuItem7Click(); Quick Save
    ExplorerControl_AllOpen(1)
EndFunc


Func OnAutoItExit()
    ConsoleWrite('CLOSED via Exit'&@CRLF)
EndFunc

Func Terminate()
    ConsoleWrite('CLOSED via Terminate'&@CRLF)
    Exit
EndFunc
A decision is a powerful thing
Link to comment
Share on other sites

Bug Report:

I'm attempting to resolve an issue where if the FolderView (browserbar) is opened and then "closed" (it's really just hidden), the FolderView will be remembered as open.

It's not capturing the control's state. Does any one know how to do that?

Local $vis = $window.Visible()
            Local $FolderBarState
            Local $BrowserBar_Ctrl = '[Class:SysTreeView32;Instance:1]'
            Local $BrowserBar_HWnd = ControlGetHandle($WindowHwnd,'',$BrowserBar_Ctrl)
            Local $BrowserBar_CtrlID = _WinAPI_GetDlgCtrlID($BrowserBar_HWnd)
            If $BrowserBar_HWnd <> 0 Then
                Local $lvPosArray = ControlGetPos($WindowHwnd,'',$FileListView_HWnd)                
                Local $browserBarState = GUICtrlGetState ( $BrowserBar_HWnd );doesn't work
                ConsoleWrite('BrowserBar State: ' &$browserBarState &@CRLF)
                ConsoleWrite('FileListView Position X: ' & $lvPosArray[0] &@CRLF)
                If $lvPosArray[0] <> 0 Then; THIS NEEDS TO BE CHANGED IN ACCORDANCE WITH THE CONTROL'S STATE
                    $FolderBarState = 1
                Else
                    $FolderBarState = 0
                EndIf
            Else
                $FolderBarState = 0
            EndIf
            
            If $vis = -1 Then
                $vis = 1
            Else
                $vis = 0
            EndIf
A decision is a powerful thing
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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...