SelectFiles(sSelect) { If (WinActive("ahk_class ExploreWClass") || WinActive("ahk_class CabinetWClass")) { hWnd:=WinExist("A") COM_Init() psh := COM_CreateObject("Shell.Application") psw := COM_Invoke(psh, "Windows") Loop, % COM_Invoke(psw, "Count") If COM_Invoke(pwb:=COM_Invoke(psw, "Item", A_Index-1), "HWND") <> hWnd COM_Release(pwb) Else Break pfv := COM_Invoke(pwb, "Document") Loop, Parse, sSelect, `n If A_LoopField <> { if(A_Index=1) COM_Invoke(pfv,"SelectItem",pfi:=COM_Invoke(pfv,"Folder.ParseName",A_LoopField),29), COM_Release(pfi) ;http://msdn.microsoft.com/en-us/library/bb774047(VS.85).aspx else COM_Invoke(pfv,"SelectItem",pfi:=COM_Invoke(pfv,"Folder.ParseName",A_LoopField),1), COM_Release(pfi) } COM_Release(pfv) COM_Release(pwb) COM_Release(psi) COM_Release(psw) COM_Release(psh) COM_Term() } }

Explorer Windows Manipulations
Started by
Sean
, Jul 02 2007 05:27 AM
99 replies to this topic
Also, here's a function for selecting files in explorer (first one in list will be focussed and scrolled to). It's based on one that I found here somewhere which didn't work for me, I adapted it using this approach to find the active window.
#61
-
Posted 28 November 2009 - 04:03 PM

You can turn off the error message and handle the errors yourself.
<!-- m -->http://www.autohotke...c22923-317.html<!-- m -->
<!-- m -->http://www.autohotke...c22923-317.html<!-- m -->
#62
-
Posted 29 November 2009 - 12:01 AM

Could do, but tbh I'd like to add support for special folders too.
ShellFolder() returns them in ::{GUID} format, but the Navigate2 COM function doesn't accept them it seems. MSDN says it accepts PIDL, but how to get it from ::{GUID}?
I was thinking to try FolderIdToCsidl() (see <!-- m -->http://msdn.microsof...ibrary/bb761736<!-- m --> ), but no success yet.
What I tried:
ShellFolder() returns them in ::{GUID} format, but the Navigate2 COM function doesn't accept them it seems. MSDN says it accepts PIDL, but how to get it from ::{GUID}?
I was thinking to try FolderIdToCsidl() (see <!-- m -->http://msdn.microsof...ibrary/bb761736<!-- m --> ), but no success yet.
What I tried:
DllCall("FolderIdToCsidl","str",sPath,"uint",csidl) DllCall("SHGetFolderLocation","uint",0,"uint", *csidl, "uint",0,"uint",ppidl) ... if(pidl) COM_Invoke(pwb, "Navigate2", *ppidl)Any ideas?
#63
-
Posted 29 November 2009 - 11:07 AM

What you saw is the CLSID of a virtual folder. And your mentioned API is about the correspondence between older CSIDL (:integer) and newer KNOWNFOLDERID (:GUID) introduced and recommended over CSIDL from Vista. But, the ultimate one the Windows shell uses to identify a file/folder is PIDL.
I deliberately avoided directly answering your question as I didn't want to go into the labor of explaining all these stuffs, and I still do, so you have to figure them out yourself if you want to use them. I'd like only to mention that it's possible to use PIDL and/or CSIDL in addition to the normal file system path with Navigate2, which is in fact the difference from Navigate.
I deliberately avoided directly answering your question as I didn't want to go into the labor of explaining all these stuffs, and I still do, so you have to figure them out yourself if you want to use them. I'd like only to mention that it's possible to use PIDL and/or CSIDL in addition to the normal file system path with Navigate2, which is in fact the difference from Navigate.
COM_Invoke(pwb, "Navigate2", 17) ; CSIDL_DRIVES:=17
#64
-
Posted 29 November 2009 - 12:51 PM

I've come to some conclusions, but no solution yet.
First, it seems that Navigate2 works with ::{CLSID} notation on XP, but not on my two Win7 systems.
This is the approach I'm currently trying, but it seems I have something wrong about the calling syntax? Maybe some pointer needs to be dereferenced?
First, it seems that Navigate2 works with ::{CLSID} notation on XP, but not on my two Win7 systems.
This is the approach I'm currently trying, but it seems I have something wrong about the calling syntax? Maybe some pointer needs to be dereferenced?
ShellNavigate(sPath, hWnd=0) { If hWnd||(hWnd:=WinExist("ahk_class CabinetWClass"))||(hWnd:=WinExist("ahk_class ExploreWClass")) { sa := Com_CreateObject("Shell.Application") wins := sa.Windows loop % wins.count if((window:=wins.Item(A_Index-1)).Hwnd=hWnd) { outputdebug found window break } DllCall("shell32\SHParseDisplayName", "Uint", COM_Unicode4Ansi(wPath,sPath) , "Uint", 0, "UintP", pidl, "Uint", 0, "Uint", 0) window.Navigate2(pidl) return } }
#65
-
Posted 29 November 2009 - 07:56 PM

Yes, you did it wrong, you can't use pidl like that. OK, some other users may also want to do this.
VarSetCapacity(sa,24,0), NumPut(DllCall("shell32\ILGetSize","Uint",pidl), NumPut(pidl, NumPut(1, NumPut(1,sa)),4)) Window.Navigate2(COM_Parameter(0x2011,&sa)) ; COM_Invoke_(Window,"Navigate2",0x2011,&sa) DllCall("shell32\ILFree","Uint",pidl)Now, you know how to use pidl with Navigate2, so, you may try to obtain directly pidl instead of Path from the opened shell windows. Actually this very script used to be in that route, but it appeared cryptic with AHK and had been changed to the current form. So, now I'll leave it as an exercise.
#66
-
Posted 30 November 2009 - 12:01 AM

This works very good, I'll post the explorer functions I'm using soon, I just want to do some testing on xp.
#67
-
Posted 01 December 2009 - 10:49 PM

I still see COM errors popping up sometimes when doing stuff in the control panel, but I haven't been able to find a reproducable case yet. This might be caused by the function being called while switching folders or similar.
Anyway, here's the functions I currently use:
Edit: Update to include fix for Steam, thanks to sinkfaze for the idea:
Anyway, here's the functions I currently use:
Edit: Update to include fix for Steam, thanks to sinkfaze for the idea:
ShellNavigate(sPath, hWnd=0) { If hWnd||(hWnd:=WinExist("ahk_class CabinetWClass"))||(hWnd:=WinExist("ahk_class ExploreWClass")) { sa := Com_CreateObject("Shell.Application") wins := sa.Windows loop % wins.count { window:=wins.Item(A_Index-1) If Not InStr( window.FullName, "steam.exe" ) ; ensure pwb isn't IE if(window.Hwnd=hWnd) break } DllCall("shell32\SHParseDisplayName", "Uint", COM_Unicode4Ansi(wPath,sPath) , "Uint", 0, "UintP", pidl, "Uint", 0, "Uint", 0) VarSetCapacity(sa,24,0), NumPut(DllCall("shell32\ILGetSize","Uint",pidl), NumPut(pidl, NumPut(1, NumPut(1,sa)),4)) Window.Navigate2(COM_Parameter(0x2011,&sa)) return } }
SelectFiles(sSelect, hWnd=0) { If hWnd||(hWnd:=WinExist("ahk_class CabinetWClass"))||(hWnd:=WinExist("ahk_class ExploreWClass")) { sa := Com_CreateObject("Shell.Application") ;Find hwnd window wins := sa.Windows loop % wins.count { window:=wins.Item(A_Index-1) If Not InStr( window.FullName, "steam.exe" ) ; ensure pwb isn't IE if(window.Hwnd=hWnd) break } doc:=window.Document Loop, Parse, sSelect, `n If A_LoopField <> { item:=COM_Invoke(doc,"Folder.ParseName",A_LoopField) ;first, deselect all but first item, then add other items to selection COM_Invoke(doc,"SelectItem",item,(A_Index=1 ? 29 : 1)) ;http://msdn.microsoft.com/en-us/library/bb774047(VS.85).aspx } } }
ShellFolder(hWnd=0,returntype=0) { If hWnd||(hWnd:=WinExist("ahk_class CabinetWClass"))||(hWnd:=WinExist("ahk_class ExploreWClass")) { sa := Com_CreateObject("Shell.Application") ;Find hwnd window wins := sa.Windows loop % wins.count { window:=wins.Item(A_Index-1) If Not InStr( window.FullName, "steam.exe" ) ; ensure pwb isn't IE if(window.Hwnd=hWnd) break } doc:=window.Document sFolder := doc.Folder.Self.Path ;Don't get focussed item and selected files unless requested, because it will cause a COM error when called during/shortly after explorer path change sometimes if (returntype=2) sFocus := doc.FocusedItem.Name if(returntype=3 || returntype=4) loop % doc.SelectedItems.Count sSelect .= (returntype=3 ? sFolder "\" COM_Invoke(doc.SelectedItems, "Item", A_Index-1).Name "`n" : COM_Invoke(doc.SelectedItems, "Item", A_Index-1).Name "`n") ;Remove last `n StringTrimRight, sSelect, sSelect, 1 if (returntype=1) Return sFolder else if (returntype=2) Return sFocus else if (returntype=3) Return sSelect else if (returntype=4) Return sSelect } }
#68
-
Posted 09 December 2009 - 05:38 PM

Hi,
I must be doing something silly but can't work it out.
When I include these last 3 functions in a test I get and error at load
The following variable name contains an illegal character:
"sa.Windows"
Obviously the dot... in (and others)
I got current COM and autohotkey.exe
I'm Using Win7 64bit
Help appreciated! :oops:
I must be doing something silly but can't work it out.
When I include these last 3 functions in a test I get and error at load
The following variable name contains an illegal character:
"sa.Windows"
Obviously the dot... in (and others)
wins := sa.Windows
I got current COM and autohotkey.exe
I'm Using Win7 64bit
Help appreciated! :oops:
#69
-
Posted 25 April 2010 - 09:31 AM

Thanks, Yogui.
_____________________________
_____________________________
That code is for Autohotkey_L.
Do something like
doc:=COM_Invoke(window,"Document")
instead of
doc:=window.Document
Or just use Autohotkey_L if it's an option for you.
Do something like
doc:=COM_Invoke(window,"Document")
instead of
doc:=window.Document
Or just use Autohotkey_L if it's an option for you.
#70
-
Posted 25 April 2010 - 10:12 AM

I set up AHK_L (asked question at the AHK_L post) http://www.autohotke...r=asc&start=509
Still having errors I have to play with it. :wink:
Your 3 functions should work in W7x64?
Still having errors I have to play with it. :wink:
Your 3 functions should work in W7x64?
#71
-
Posted 26 April 2010 - 01:15 AM

Thanks, Yogui.
_____________________________
_____________________________
Hi,
This should work but it does not :cry:
^1 Does Nothing
^2 Gives errors
Function Name: "Folder"
ERROR: No COM Dispatch Object!
()
^3 All four are a Space
This should work but it does not :cry:
^1 Does Nothing
^2 Gives errors
Function Name: "Folder"
ERROR: No COM Dispatch Object!
()
^3 All four are a Space
Return #Include %A_ScriptDir%\COM.ahk ;COM L version is in the same dir ;============================================================================== ^1 Up:: KeyWait, Control ShellNavigate(A_ScriptDir, WinExist("A")) Return ;============================================================================== ^2 Up:: KeyWait, Control SelectFiles(A_ScriptFullPath, WinExist("A")) Return ;============================================================================== ^3 Up:: KeyWait, Control Type1 := ShellFolder(WinExist("A"),1) Type2 := ShellFolder(WinExist("A"),2) Type3 := ShellFolder(WinExist("A"),3) Type4 := ShellFolder(WinExist("A"),4) ToolTip, Type1: >%Type1%<`nType2: >%Type2%<`nType3: >%Type3%<`nType4: >%Type4%< Return ;From http://www.autohotkey.com/forum/topic20701-60.html ShellNavigate(sPath, hWnd=0) { If hWnd||(hWnd:=WinExist("ahk_class CabinetWClass"))||(hWnd:=WinExist("ahk_class ExploreWClass")) { sa := Com_CreateObject("Shell.Application") wins := sa.Windows loop % wins.count { window:=wins.Item(A_Index-1) If Not InStr( window.FullName, "steam.exe" ) ; ensure pwb isn't IE if(window.Hwnd=hWnd) break } DllCall("shell32\SHParseDisplayName", "Uint", COM_Unicode4Ansi(wPath,sPath) , "Uint", 0, "UintP", pidl, "Uint", 0, "Uint", 0) VarSetCapacity(sa,24,0), NumPut(DllCall("shell32\ILGetSize","Uint",pidl), NumPut(pidl, NumPut(1, NumPut(1,sa)),4)) Window.Navigate2(COM_Parameter(0x2011,&sa)) return } } SelectFiles(sSelect, hWnd=0) { If hWnd||(hWnd:=WinExist("ahk_class CabinetWClass"))||(hWnd:=WinExist("ahk_class ExploreWClass")) { sa := Com_CreateObject("Shell.Application") ;Find hwnd window wins := sa.Windows loop % wins.count { window:=wins.Item(A_Index-1) If Not InStr( window.FullName, "steam.exe" ) ; ensure pwb isn't IE if(window.Hwnd=hWnd) break } doc:=window.Document Loop, Parse, sSelect, `n If A_LoopField <> { item:=COM_Invoke(doc,"Folder.ParseName",A_LoopField) ;first, deselect all but first item, then add other items to selection COM_Invoke(doc,"SelectItem",item,(A_Index=1 ? 29 : 1)) ;http://msdn.microsoft.com/en-us/library/bb774047(VS.85).aspx } } } ShellFolder(hWnd=0,returntype=0) { If hWnd||(hWnd:=WinExist("ahk_class CabinetWClass"))||(hWnd:=WinExist("ahk_class ExploreWClass")) { sa := Com_CreateObject("Shell.Application") ;Find hwnd window wins := sa.Windows loop % wins.count { window:=wins.Item(A_Index-1) If Not InStr( window.FullName, "steam.exe" ) ; ensure pwb isn't IE if(window.Hwnd=hWnd) break } doc:=window.Document sFolder := doc.Folder.Self.Path ;Don't get focussed item and selected files unless requested, because it will cause a COM error when called during/shortly after explorer path change sometimes if (returntype=2) sFocus := doc.FocusedItem.Name if(returntype=3 || returntype=4) loop % doc.SelectedItems.Count sSelect .= (returntype=3 ? sFolder "\" COM_Invoke(doc.SelectedItems, "Item", A_Index-1).Name "`n" : COM_Invoke(doc.SelectedItems, "Item", A_Index-1).Name "`n") ;Remove last `n StringTrimRight, sSelect, sSelect, 1 if (returntype=1) Return sFolder else if (returntype=2) Return sFocus else if (returntype=3) Return sSelect else if (returntype=4) Return sSelect } }
#73
-
Posted 27 April 2010 - 11:31 AM

Thanks, Yogui.
_____________________________
_____________________________
Sorry I forgot to mention.
I'm not good enough with COM to understand whats wrong. :oops:
If I try modify your functions to run with normal AHK (as you sugested before).
What would it happen with the calls to:
I'm not good enough with COM to understand whats wrong. :oops:
If I try modify your functions to run with normal AHK (as you sugested before).
What would it happen with the calls to:
COM_Parameter
#74
-
Posted 27 April 2010 - 11:36 AM

Thanks, Yogui.
_____________________________
_____________________________
Use the edit function 
You still have sa.Windows in the script you posted.
I didn't check any further, make sure not to use the dot operator for something like this in vanilla AHK.

You still have sa.Windows in the script you posted.
I didn't check any further, make sure not to use the dot operator for something like this in vanilla AHK.
#75
-
Posted 27 April 2010 - 06:59 PM
