LarsJ Posted July 8, 2020 Share Posted July 8, 2020 (edited) This is an update of the old Automating Windows Explorer example. The update includes Desktop automation. However, Windows XP code has been removed. ThreadsOther threads related to File/Windows Explorer: Implementing Windows Explorer right pane Implementing Windows Explorer address bar Enumerating and Browsing the Desktop Some of these threads are very old. I'm considering updating some of the examples: Remove Windows XP code. Implement some of the code in other ways. Enumerating and Browsing the Desktop is important to me personally because it was the first time I used the ObjCreateInterface() function. The first version of the example was based on _AutoItObject_WrapperCreate() from the AutoItObject UDF. Then I was told that you can use ObjCreateInterface() instead. Of course I had to try. Automating File/Windows Explorer and DesktopAutomating File/Windows ExplorerThe old example contains a description of the techniques for automating File/Windows Explorer. The techniques are based on COM interfaces. Initially, it's about getting an IShellBrowser interface based on a File/Windows Explorer window handle. An IDispatch interface for the window is important for creating the IShellBrowser interface. Through the IShellBrowser interface, you can generate a large number of interfaces that can be used to implement the automation functions. Automating DesktopBilgus figured out how to get an IDispatch interface for the Desktop in this post: $oIShellWindows.FindWindowSW( Null, Null, $SWC_DESKTOP, $hWnd, $SWFO_NEEDDISPATCH, $pIDispatch ) This is the part of the old code in the GetIShellBrowser() function that needs to be updated to include the Desktop: ; Get an IWebBrowserApp object for each window ; This is done in two steps: ; 1. Get an IDispatch object for the window ; 2. Get the IWebBrowserApp interface ; Check if it's the right window Local $pIDispatch, $oIDispatch Local $pIWebBrowserApp, $oIWebBrowserApp, $hWnd For $i = 0 To $iWindows - 1 $oIShellWindows.Item( $i, $pIDispatch ) If $pIDispatch Then $oIDispatch = ObjCreateInterface( $pIDispatch, $sIID_IDispatch, $dtag_IDispatch ) $oIDispatch.QueryInterface( $tRIID_IWebBrowserApp, $pIWebBrowserApp ) If $pIWebBrowserApp Then $oIWebBrowserApp = ObjCreateInterface( $pIWebBrowserApp, $sIID_IWebBrowserApp, $dtag_IWebBrowserApp ) $oIWebBrowserApp.get_HWND( $hWnd ) If $hWnd = $hExplorer Then ExitLoop EndIf EndIf Next And here the code to include the Desktop is added: ; Get an IWebBrowserApp object for each window ; This is done in two steps: ; 1. Get an IDispatch object for the window ; 2. Get the IWebBrowserApp interface ; Check if it's the right window Local $pIDispatch, $oIDispatch, $hRes Local $pIWebBrowserApp, $oIWebBrowserApp, $hWnd For $i = 0 To $iWindows $hRes = $i < $iWindows ? $oIShellWindows.Item( $i, $pIDispatch ) _ : $oIShellWindows.FindWindowSW( Null, Null, $SWC_DESKTOP, $hWnd, $SWFO_NEEDDISPATCH, $pIDispatch ) If $pIDispatch Then $oIDispatch = ObjCreateInterface( $pIDispatch, $sIID_IDispatch, $dtag_IDispatch ) $oIDispatch.QueryInterface( $tRIID_IWebBrowserApp, $pIWebBrowserApp ) If $pIWebBrowserApp Then $oIWebBrowserApp = ObjCreateInterface( $pIWebBrowserApp, $sIID_IWebBrowserApp, $dtag_IWebBrowserApp ) $oIWebBrowserApp.get_HWND( $hWnd ) If $hWnd = $hExplorer Then ExitLoop EndIf EndIf Next The For loop runs an extra round if a File/Explorer Window has not been identified. In this last loop, the FindWindowSW() method returns a window corresponding to the Desktop. Here, the method always returns the Program Manager window. a consequence of this implementation is that if you specify a non-existent window as a parameter to the GetIShellBrowser() function, then the function will return the Program Manager window. Thus, the Program Manager window is the default window for the function. The IDispatch interface is the important thing in terms of automating the Desktop. Then all the functions used in connection with a File/Windows Explorer window can also be used in connection with the Desktop. Except for a few functions that are not relevant for the Desktop. Functions The automation functions are coded in FileExplorer.au3. The functions are implemented using a number of Shell API functions and Shell COM interfaces coded in ShellFunctions.au3 and ShellInterfaces.au3. The old example contains a list of implemented functions. New functions GetSortColumns() GetSortColumnsEx() SetSortColumns() Examples The 7z-file contains examples for automating the Desktop and a File/Windows Explorer window. These are the same examples as in this post. Note that the examples GetFiles.au3 and GetFolders.au3 also show how to make a list of selected files and folders. Note that the GetSetIconView.au3 example can change the order of icons on the Desktop. If you don't want this, run this example only in a File/Windows Explorer window. The GUI application that was used to demonstrate the features in the old version is not included. The small examples seems to be much more useful. This post contains new examples. In both the old and the new post, the examples are shown for a File/Windows Explorer window. But the 7z-file contains similar examples for the Desktop. Forum examplesThis is a list of the most interesting examples in the old thread: The original collection of small examples Automate a file search with UI Automation code. The question that led to this answer was asked in a slightly earlier post. Execute a function on a double-click in empty space of the listview. Based on UI Automation code. Here the question was asked somewhat earlier. UI Automation code to make a selected item visible by scrolling the listview up or down 7z-fileThe 7z-file contains source code for the UDF and examples. You need AutoIt 3.3.12 or later. Tested on Windows 7 and Windows 10. Comments are welcome. Let me know if there are any issues. FileExplorerAndDesktop.7z Edited July 26, 2020 by LarsJ Updates and new 7z-file Earthshine, ptrex, KaFu and 1 other 4 Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
LarsJ Posted July 12, 2020 Author Share Posted July 12, 2020 Added more information to first post. Minor updates of the examples. New 7z-file at bottom of first post. Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
LarsJ Posted July 23, 2020 Author Share Posted July 23, 2020 (edited) GetSortColumns()Added a new function to show which column(s) a File/Windows Explorer or Desktop view is sorted by: Func GetSortColumns() Local $iColumns ; Number of sort columns $oIFolderView2.GetSortColumnCount( $iColumns ) ; Get sort columns Local $tagSORTCOLUMNS For $i = 0 To $iColumns - 1 $tagSORTCOLUMNS &= $tagSORTCOLUMN & ";" Next Local $tSortColumns = DllStructCreate( $tagSORTCOLUMNS ) $oIFolderView2.GetSortColumns( $tSortColumns, $iColumns ) ; Get data from structure Local $tSC, $aSortColumns[2*$iColumns][2] For $i = 0 To $iColumns - 1 $aSortColumns[2*$i+0][0] = "Sort" $aSortColumns[2*$i+1][0] = "Column" $tSC = DllStructCreate( $tagSORTCOLUMN, DllStructGetPtr( $tSortColumns ) + $i * DllStructGetSize( $tSortColumns ) ) $aSortColumns[2*$i+0][1] = DllStructGetData( $tSC, "sort" ) PSGetNameFromPropertyKey( DllStructGetPtr( $tSC ), $aSortColumns[2*$i+1][1] ) If @error Then PSStringFromPropertyKey( DllStructGetPtr( $tSC ), $aSortColumns[2*$i+1][1] ) Next ; Return sort columns Return $aSortColumns EndFunc Because the information is extracted from PropertyKeys, column names are displayed this way: Name -> System.ItemNameDisplay Date modified -> System.DateModified Type -> System.ItemTypeText Size -> System.Size When I sort files by Type in a Windows Explorer window, I get this information about the sort columns: Sort -> -1 Column -> System.ItemTypeText Sort -> 0 Column -> {EB4F9DAB-0000-0000-91B9-413D76000090} 0 There are two sort columns. The first is the Type column, which is sorted in descending order. The other doesn't immediately provide any recognizable information. But it's probably used by the internal Microsoft code. Two new examples. One for the Desktop and one for an Explorer window. Note that the Desktop example on Windows 10 simply shows an empty ArrayDisplay window. This is because the Name column for the Desktop is not provided with a sort. So $iColumns in the code box above gets the value zero. And thus $aSortColumns becomes an empty array. Probably there is no sorting for the other columns either (the columns can be seen in Details view). Sorting for the Name column can be set with the code in the next post. And then the sort is displayed in the ArrayDisplay window. Note that setting a sort for the Name column means that the icons on the Desktop are placed in a different order. Edited July 26, 2020 by LarsJ Updates Earthshine 1 Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
LarsJ Posted July 26, 2020 Author Share Posted July 26, 2020 SetSortColumns()The SetSortColumns() function to set the sort for a column (the columns that can be seen in Details view) is coded this way: Func SetSortColumns( $sGUID, $iPID, $iSort ) ; Create SORTCOLUMN structure Local $tSortColumn = DllStructCreate( $tagSORTCOLUMN ) _WinAPI_GUIDFromStringEx( $sGUID, $tSortColumn ) DllStructSetData( $tSortColumn, "pid", $iPID ) DllStructSetData( $tSortColumn, "sort", $iSort ) ; Set sort columns $oIFolderView2.SetSortColumns( $tSortColumn, 1 ) EndFunc This is the Microsoft definition of the IFolderView2.SetSortColumns() method: HRESULT SetSortColumns( SORTCOLUMN *rgSortColumns, // Structure int cColumns // Integer, number of columns ) // SORTCOLUMN structure struct tagSORTCOLUMN { PROPERTYKEY propkey; // Structure SORTDIRECTION direction; // Integer, sort direction, 1 or -1 } // PROPERTYKEY structure struct tagPROPERTYKEY { GUID fmtid; // Unique identifier of the PROPERTYKEY dword pid; // Property identifier (PID) } And these are the AutoIt definitions: ; PROPERTYKEY Structure (GUID & PID) Global Const $tagPROPERTYKEY = "struct;ulong Data1;ushort Data2;ushort Data3;byte Data4[8];endstruct" & ";dword pid" ; SORTCOLUMN Structure Global Const $tagSORTCOLUMN = $tagPROPERTYKEY & ";int sort" The information needed for the SetSortColumns() function to create the SORTCOLUMN structure is therefore $sGUID and $iPID, which defines the PROPERTYKEY structure, and $iSort, which defines the final SORTCOLUMN structure. To obtain $sGUID and $iPID from a PROPERTYKEY structure, a new function GetSortColumnsEx() has been added, which returns $sGUID and $iPID in addition to the original information from GetSortColumns(). Output from GetSortColumnsEx() for System.ItemNameDisplay PropertyKey: GUID -> {B725F130-47EF-101A-A5F1-02608C9EEBAC} PID -> 10 Sort -> 1 Column -> System.ItemNameDisplay Because the first part of the PROPERTYKEY structure is a GUID, the value of this GUID can be set with _WinAPI_GUIDFromStringEx(). Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
LarsJ Posted July 26, 2020 Author Share Posted July 26, 2020 (edited) ExamplesThe examples are shown for a File/Windows Explorer window. The 7z-file at bottom of first post contains similar examples for the Desktop. 8 ) GetSortColumns.au3 #include "..\..\Includes\FileExplorer.au3" #include <Array.au3> Example() Func Example() ; File/Windows Explorer on Windows 7, 8, 10 Local $hExplorer = WinGetHandle( "[REGEXPCLASS:^(Cabinet|Explore)WClass$]" ) If Not $hExplorer Then MsgBox( 0, "Automating File/Windows Explorer and Desktop", "Could not find window. Terminating." ) Return EndIf ; Get an IShellBrowser interface GetIShellBrowser( $hExplorer ) If Not IsObj( $oIShellBrowser ) Then MsgBox( 0, "Automating File/Windows Explorer and Desktop", "Could not get an IShellBrowser interface. Terminating." ) Return EndIf ; Activate File Explorer WinActivate( $hExplorer ) WinWaitActive( $hExplorer ) ; Get other interfaces GetShellInterfaces() ; Get sort columns Local $aSortColumns = GetSortColumns() _ArrayDisplay( $aSortColumns, "Explorer: $aSortColumns" ) EndFunc Output: Sort -> 1 Column -> System.ItemNameDisplay 9) GetSortColumnsEx.au3 #include "..\..\Includes\FileExplorer.au3" #include <Array.au3> Example() Func Example() ; File/Windows Explorer on Windows 7, 8, 10 Local $hExplorer = WinGetHandle( "[REGEXPCLASS:^(Cabinet|Explore)WClass$]" ) If Not $hExplorer Then MsgBox( 0, "Automating File/Windows Explorer and Desktop", "Could not find window. Terminating." ) Return EndIf ; Get an IShellBrowser interface GetIShellBrowser( $hExplorer ) If Not IsObj( $oIShellBrowser ) Then MsgBox( 0, "Automating File/Windows Explorer and Desktop", "Could not get an IShellBrowser interface. Terminating." ) Return EndIf ; Activate File Explorer WinActivate( $hExplorer ) WinWaitActive( $hExplorer ) ; Get other interfaces GetShellInterfaces() ; Get sort columns Local $aSortColumns = GetSortColumnsEx() _ArrayDisplay( $aSortColumns, "Explorer: $aSortColumns" ) EndFunc Output: GUID -> {B725F130-47EF-101A-A5F1-02608C9EEBAC} PID -> 10 Sort -> 1 Column -> System.ItemNameDisplay 10) SetSortColumns.au3 #include "..\..\Includes\FileExplorer.au3" Example() Func Example() ; File/Windows Explorer on Windows 7, 8, 10 Local $hExplorer = WinGetHandle( "[REGEXPCLASS:^(Cabinet|Explore)WClass$]" ) If Not $hExplorer Then MsgBox( 0, "Automating File/Windows Explorer and Desktop", "Could not find window. Terminating." ) Return EndIf ; Get an IShellBrowser interface GetIShellBrowser( $hExplorer ) If Not IsObj( $oIShellBrowser ) Then MsgBox( 0, "Automating File/Windows Explorer and Desktop", "Could not get an IShellBrowser interface. Terminating." ) Return EndIf ; Activate File Explorer WinActivate( $hExplorer ) WinWaitActive( $hExplorer ) ; Get other interfaces GetShellInterfaces() ; Set sort columns SetSortColumns( "{B725F130-47EF-101A-A5F1-02608C9EEBAC}", 10, -1 ) ; System.ItemNameDisplay, Name EndFunc Desktop: Note that setting a sort for the Name column on Desktop means that the icons are placed in a different order. First post and GetSortColumns() post are updated. This post and previous post have been added. New 7z-file at bottom of first post. Edited July 26, 2020 by LarsJ Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now