Trolleule Posted March 3, 2014 Share Posted March 3, 2014 Hi I'm trying to make a custom filtering with the shell function SHBrowseForFolder and i actually work with the example from the autoit help file. I catch the IUnknown event and the lparam contains a pointer to an IUnknown interface. Can someone explain please what i can generally do with an interface pointer. And how can i get an single level pidl from an absolute pidl. I study the msdn sites for days but i dont get it. I only understand how i can make an object with an specified interface to use its methods. But the most methods need a pidl item and i only have an pidl folder. Thanks for help! Link to comment Share on other sites More sharing options...
LarsJ Posted March 4, 2014 Share Posted March 4, 2014 (edited) Trolleule, I saw your post (Select Folder/File (_WinAPI_BrowseForFolderDlg()) mit Filter Option: PIDL (IDLIST) auslesen) about this subject in the German forum while the English forum was down.You generally use an interface pointer to create an interface object to be able to call the methods of the object.For point 3. in the middle of your German post you create an IUnknown object from the pointer like this:; IUnknown Interface Global Const $sIID_IUnknown = "{00000000-0000-0000-C000-000000000046}" Global Const $tRIID_IUnknown = _WinAPI_GUIDFromString( $sIID_IUnknown ) Global Const $dtag_IUnknown = _ "QueryInterface hresult(struct*;ptr*);" & _ "AddRef ulong();" & _ "Release ulong();" $oIUnknown = ObjCreateInterface( $pIUnknown, $sIID_IUnknown, $dtag_IUnknown )Still in point 3. you use QueryInterface to get a pointer for IFolderFilterSite:Global Const $sIID_IFolderFilterSite = "{C0A651F5-B48B-11d2-B5ED-006097C686F6}" Global Const $tRIID_IFolderFilterSite = _WinAPI_GUIDFromString( $sIID_IFolderFilterSite ) Global Const $dtag_IFolderFilterSite = "SetFilter hresult(ptr);" Local $pIFolderFilterSite $oIUnknown.QueryInterface( $tRIID_IFolderFilterSite, $pIFolderFilterSite ) $oIFolderFilterSite = ObjCreateInterface( $pIFolderFilterSite, $sIID_IFolderFilterSite, $dtag_IFolderFilterSite )Point 4. It's too late now. I'll be back. Edited March 4, 2014 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...
LarsJ Posted March 4, 2014 Share Posted March 4, 2014 I have done a few tests. Creation of the IUnknown object fails with an 0xC0000005 error. I'll try to figure out why.The German post: http://www.autoit.de/index.php?page=Thread&threadID=44841 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 March 5, 2014 Share Posted March 5, 2014 I've looked in the documentation. You must specify the pointer to IUnknown in lParam of the BROWSEINFO structure before you call SHBrowseForFolder. This means that you must start to create an interface object. This can probably be done (more or less in the same manner as in Implementing Windows Explorer right pane), but it takes a lot more work. I will not go on with this. 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...
Trolleule Posted March 6, 2014 Author Share Posted March 6, 2014 (edited) sorry for late reply. Thank you very much for your help Lars. Her is the code iam testing with: If you want to use my code, you have to copy the WinAPIDlg.au3 and delete the _WinAPI_BrowseForFolderDlg there cause i overwrite it in my code or you rename the function in my code. expandcollapse popup#include "WinAPIDlg.au3" ;#include "AutoItObject.au3" #include <APIDlgConstants.au3> #include <WinAPISys.au3> #include <MsgBoxConstants.au3> ;#include "_DLLStructDisplay.au3" Global Const $InitDir = @ProgramFilesDir ;=============================================================================== #interface "IUnknown" ;~ Global Const $sIID_IUnknown = "{00000000-0000-0000-C000-000000000046}" ; Definition Global $dtagIUnknown = "QueryInterface hresult(ptr;ptr*);" & _ "AddRef dword();" & _ "Release dword();" ; List Global $ltagIUnknown = "QueryInterface;" & _ "AddRef;" & _ "Release;" ;=============================================================================== ;=============================================================================== #interface "IDispatch" ;~ Global Const $sIID_IDispatch = "{00020400-0000-0000-C000-000000000046}" ; Definition Global $dtagIDispatch = $dtagIUnknown & _ "GetTypeInfoCount hresult(dword*);" & _ "GetTypeInfo hresult(dword;dword;ptr*);" & _ "GetIDsOfNames hresult(ptr;ptr;dword;dword;ptr);" & _ "Invoke hresult(dword;ptr;dword;word;ptr;ptr;ptr;ptr);" ; List Global $ltagIDispatch = $ltagIUnknown & _ "GetTypeInfoCount;" & _ "GetTypeInfo;" & _ "GetIDsOfNames;" & _ "Invoke;" ;=============================================================================== #interface "IShellFolder" Global Const $sIID_IShellFolder = "{000214E6-0000-0000-C000-000000000046}" Global $tagIShellFolder = "ParseDisplayName hresult(hwnd;ptr;wstr;ulong*;ptr*;ulong*);" & _ "EnumObjects hresult(hwnd;dword;ptr*);" & _ "BindToObject hresult(struct*;ptr;clsid;ptr*);" & _ "BindToStorage hresult(struct*;ptr;clsid;ptr*);" & _ "CompareIDs hresult(lparam;struct*;struct*);" & _ "CreateViewObject hresult(hwnd;clsid;ptr*);" & _ "GetAttributesOf hresult(uint:struct*;ulong*);" & _ "GetUIObjectOf hresult(hwnd;uint;struct*;clsid;uint*;ptr*);" & _ "GetDisplayNameOf hresult(struct*;dword;struct*);" & _ "SetNameOf hresult(hwnd;struct*;wstr;dword;struct*);" ;=============================================================================== ;=============================================================================== #interface "IShellItem" Global Const $sIID_IShellItem = "{43826d1e-e718-42ee-bc55-a1e261c37bfe}" Global $tagIShellItem = "BindToHandler hresult(ptr;clsid;clsid;ptr*);" & _ "GetParent hresult(ptr*);" & _ "GetDisplayName hresult(int;ptr*);" & _ "GetAttributes hresult(int;int*);" & _ "Compare hresult(ptr;int;int*);" ;=============================================================================== ;=============================================================================== #interface "IShellItemArray" Global Const $sIID_IShellItemArray = "{b63ea76d-1f85-456f-a19c-48159efa858b}" Global $tagIShellItemArray = "BindToHandler hresult(ptr;clsid;clsid;ptr*);" & _ "GetPropertyStore hresult(int;clsid;ptr*);" & _ "GetPropertyDescriptionList hresult(struct*;clsid;ptr*);" & _ "GetAttributes hresult(int;int;int*);" & _ "GetCount hresult(dword*);" & _ "GetItemAt hresult(dword;ptr*);" & _ "EnumItems hresult(ptr*);" ;=============================================================================== ;=============================================================================== #interface "IModalWindow" Global Const $sIID_IModalWindow = "{b4db1657-70d7-485e-8e3e-6fcb5a5c1802}" Global $tagIModalWindow = "Show hresult(hwnd);" ;=============================================================================== ;=============================================================================== #interface "IFileDialog" Global Const $sIID_IFileDialog = "{42f85136-db7e-439c-85f1-e4075d135fc8}" Global $tagIFileDialog = $tagIModalWindow & _ "SetFileTypes hresult(uint;ptr);" & _ "SetFileTypeIndex hresult(uint);" & _ "GetFileTypeIndex hresult(uint*);" & _ "Advise hresult(ptr;dword*);" & _ "Unadvise hresult(dword);" & _ "SetOptions hresult(int);" & _ "GetOptions hresult(int*);" & _ "SetDefaultFolder hresult(ptr);" & _ "SetFolder hresult(ptr);" & _ "GetFolder hresult(ptr*);" & _ "GetCurrentSelection hresult(ptr*);" & _ "SetFileName hresult(wstr);" & _ "GetFileName hresult(ptr*);" & _ "SetTitle hresult(wstr);" & _ "SetOkButtonLabel hresult(wstr);" & _ "SetFileNameLabel hresult(wstr);" & _ "GetResult hresult(ptr*);" & _ "AddPlace hresult(ptr;int);" & _ "SetDefaultExtension hresult(wstr);" & _ "Close hresult();" & _ "SetClientGuid hresult(clsid);" & _ "ClearClientData hresult();" & _ "SetFilter hresult(ptr);" ;=============================================================================== ;=============================================================================== #interface "IFileOpenDialog" Global Const $sCLSID_FileOpenDialog = "{DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7}" Global Const $sIID_IFileOpenDialog = "{d57c7288-d4ad-4768-be02-9d969532d960}" Global $tagIFileOpenDialog = $tagIFileDialog & _ "GetResults hresult(ptr*);" & _ "GetSelectedItems hresult(ptr*);" ;=============================================================================== ;~ #interface "IFolderFilter" ;~ Global Const $sCLSID_FileOpenDialog = "{DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7}" Global Const $sIID_IFolderFilter = "{9CC22886-DC8E-11D2-B1D0-00C04F8EEB3E}" Global $tagIFolderFilter = "ShouldShow hresult(ptr*;ptr;ptr);" & _ "GetEnumFlags hresult(ptr*;ptr;hwnd*;dword*);" Local Const $tagITEMIDLIST = 'ptr mkid' Local Const $tagSHITEMID = 'ushort cb;byte abID' Global Const $SIGDN_NORMALDISPLAY = 0 ;~ Local $poi = _AutoItObject_WrapperCreate($ptr_IShellFolder[1],$tagIShellFolder) ;~ ConsoleWrite("Object: " & $poi & " type: " & VarGetType($poi) & @CRLF) Local $ptr_IShellFolder = GetDesktop() ; ptr to shellfolder interface ;~ _ArrayDisplay($ptr_IShellFolder) ConsoleWrite("desktop_pidl: " & $ptr_IShellFolder[1] & " type: " & VarGetType($ptr_IShellFolder[1]) & @CRLF) Func GetDesktop() Local $Ret = DllCall('shell32.dll', 'ptr', 'SHGetDesktopFolder', 'ptr*', 0) Return $Ret EndFunc Local $structptrs = DllStructCreate("ptr[100]", $ptr_IShellFolder[1]) ;~ _DLLStructDisplay($structptrs,"ptr[100]","Randomness") Local $hBrowseProc = DllCallbackRegister('_BrowseProc', 'int', 'hwnd;uint;lparam;ptr') Local $pBrowseProc = DllCallbackGetPtr($hBrowseProc) Local $pText = _WinAPI_CreateString($InitDir) Local $Path = _WinAPI_BrowseForFolderDlg(_WinAPI_PathStripToRoot($InitDir), 'Select a folder from the list below.', _ BitOR($BIF_BROWSEINCLUDEFILES, $BIF_NEWDIALOGSTYLE, $BIF_EDITBOX, $BIF_VALIDATE), $pBrowseProc, $pText) _WinAPI_FreeMemory($pText) If $Path Then ConsoleWrite('--------------------------------------------------' & @CRLF) ConsoleWrite($Path & @CRLF) EndIf DllCallbackFree($hBrowseProc) Func _BrowseProc($hWnd, $iMsg, $wParam, $lParam) Local $Path Switch $iMsg Case $BFFM_INITIALIZED _WinAPI_SetWindowText($hWnd, 'MyTitle') _SendMessage($hWnd, $BFFM_SETSELECTIONW, 1, $lParam) ConsoleWrite("Initialize" & @CRLF) Case $BFFM_SELCHANGED ;~ $Path = _WinAPI_ShellGetPathFromIDList($wParam) ;~ If Not @error Then ;~ ConsoleWrite($Path & @CRLF) ;~ EndIf Case $BFFM_VALIDATEFAILED MsgBox(BitOR($MB_ICONERROR, $MB_SYSTEMMODAL), 'Error', _WinAPI_GetString($wParam) & ' is invalid.', 0, $hWnd) Return 1 Case $BFFM_IUNKNOWN ConsoleWrite("lparam: " & $lParam & " type: " & VarGetType($lParam) & @CRLF) ;~ Local $test = ObjCreateInterface($lParam, $sIID_IShellFolder, $tagIShellFolder) Local $test = ObjCreateInterface($sCLSID_FileOpenDialog, $sIID_IFolderFilter, $tagIFolderFilter) ConsoleWrite("ref: " & $test & " type: " & VarGetType($test) & @CRLF) Local $ab = $test.AddRef() ConsoleWrite("ref: " & $ab & " type: " & VarGetType($ab) & @CRLF) Local $Path = _WinAPI_ShellGetPathFromIDList($wParam) Local $PIDL = $wParam Local $oShellFolder = ObjCreateInterface("{0E5AAE11-A475-4C5B-AB00-C66DE400274E}", $sIID_IShellFolder, $tagIShellFolder) ConsoleWrite("reff: " & $oShellFolder & " type: " & VarGetType($oShellFolder) & @CRLF) Local $ptrs = DllStructCreate("ptr[100]", $PIDL) ;~ _DLLStructDisplay($ptrs,"ptr[100]","Randomness") Local $out_name Local $name = $oShellFolder.GetDisplayNameOf($PIDL, $SIGDN_NORMALDISPLAY, $out_name) ConsoleWrite("hresult displayname: " & Hex($name) & @CRLF) EndSwitch Return 0 EndFunc ;==>_BrowseProc Func GetFolderLocation() ;~ Local $Ret = DllCall('shell32.dll', 'ptr', 'SHGetFolderLocation', 'ptr*', 0) EndFunc Func _SHBindToParent($pidl, $riid, ByRef $pv, ByRef $pidlLast) Local $aRes = DllCall("Shell32.dll", "long", "SHBindToParent", "ptr", $pidl, "ptr", $riid, "ptr*", 0, "ptr*", 0) If @error Then Return SetError(1, 0, 0) $pv = $aRes[3] $pidlLast = $aRes[4] Return $aRes[0] EndFunc ;==>_SHBindToParent Func _IShellFolder_StrRetToBuf($pSTRRET, $pidl, ByRef $sName, $iLength = 512) Local $aRes = DllCall("shlwapi.dll", "long", "StrRetToBufW", "ptr", $pSTRRET, "ptr", $pidl, "wstr", $sName, "uint", $iLength) If @error Then Return SetError(1, 0, 0) $sName = $aRes[3] Return $aRes[0] EndFunc ;==>_IShellFolder_StrRetToBuf Func _WinAPI_BrowseForFolderDlg($sRoot = '', $sText = '', $iFlags = 0, $pBrowseProc = 0, $lParam = 0, $hParent = 0) Local Const $tagBROWSEINFO = 'hwnd hwndOwner;ptr pidlRoot;ptr pszDisplayName; ptr lpszTitle;uint ulFlags;ptr lpfn;lparam lParam;int iImage' Local $tBROWSEINFO = DllStructCreate($tagBROWSEINFO & ';wchar[' & (StringLen($sText) + 1) & '];wchar[260]') Local $PIDL = 0, $Result = '' If StringStripWS($sRoot, 3) Then Local $Path = _WinAPI_PathSearchAndQualify($sRoot, 1) If @error Then $Path = $sRoot EndIf $PIDL = _WinAPI_ShellILCreateFromPath($Path) ; get ptr from path If @error Then ; Nothing EndIf EndIf ConsoleWrite("pIDL from path: " & $PIDL & @CRLF) DllStructSetData($tBROWSEINFO, 1, $hParent) DllStructSetData($tBROWSEINFO, 2, $PIDL) DllStructSetData($tBROWSEINFO, 3, DllStructGetPtr($tBROWSEINFO, 10)) DllStructSetData($tBROWSEINFO, 4, DllStructGetPtr($tBROWSEINFO, 9)) DllStructSetData($tBROWSEINFO, 5, $iFlags) DllStructSetData($tBROWSEINFO, 6, $pBrowseProc) DllStructSetData($tBROWSEINFO, 7, $lParam) DllStructSetData($tBROWSEINFO, 8, 0) DllStructSetData($tBROWSEINFO, 9, $sText) Local $Ret = DllCall('shell32.dll', 'ptr', 'SHBrowseForFolderW', 'struct*', $tBROWSEINFO) ; returns PIDLIST_ABSOLUTE If @error Or Not $Ret[0] Then Return SetError(@error, @extended, '') ; If Not $Ret[0] Then Return SetError(1000, 0, '') ;~ _ArrayDisplay($Ret) ConsoleWrite("out pidl: " & $Ret[0] & @CRLF) Local $ptrs = DllStructCreate("ptr[100]", $Ret[0]) ;~ _DLLStructDisplay($ptrs,"ptr[100]","Randomness") ;~ Local $stru = DllStructCreate($tagITEMIDLIST) Local $pidlLast Local $pv Local $binder = _SHBindToParent($Ret[0], $sIID_IShellFolder, $pv, $pidlLast) _ArrayDisplay($binder) ConsoleWrite("out pidl child: " & $pidlLast & @CRLF) ConsoleWrite("out interface ptr: " & $pv & @CRLF) ConsoleWrite("hresult binder: " & $binder & @CRLF) ; $Ret[0] = PIDL: ; The address of an item identifier list that specifies a file or directory location relative to the ; root of the namespace ; Return: The file system path $Result = _WinAPI_ShellGetPathFromIDList($Ret[0]) ConsoleWrite("GetPathFromPIDL: " & $Result & @CRLF) _WinAPI_CoTaskMemFree($Ret[0]) If $PIDL Then _WinAPI_CoTaskMemFree($PIDL) EndIf If Not $Result Then Return SetError(10, 0, '') Return $Result EndFunc ;==>_WinAPI_BrowseForFolderDlg Check the code where i cathc the IUnknown event: There i created a IShellFolder Interface successfully. But now i want to execute the GetDisplayNameOf method: HRESULT GetDisplayNameOf( [in] PCUITEMID_CHILD pidl, [in] SHGDNF uFlags, [out] STRRET *pName ); Check msdn http://msdn.microsoft.com/en-us/library/windows/desktop/bb775071(v=vs.85).aspx I hope and i think my final question is how i can get an PCUITEMID_CHILD(PIDL that uniquely identifies the file object or subfolder relative to the parent folder.) of an PIDLIST_ABSOLUTE (Returns a PIDL that specifies the location of the selected folder relative to the root of the namespace. ) If i understand right, a PIDLIST_ABSOLUTE is a list of "itemid" structures and a PCUITEMID_CHILD is a single "itemid" structure?! Anyway, if a pidl is a list, it must be possible to iterate this list and get all the files/folders inside the pidl as ?IShellItem? or get the name of the files/folders with GetDisplayNameOf. Can you help? Edited March 6, 2014 by Trolleule Link to comment Share on other sites More sharing options...
LarsJ Posted March 7, 2014 Share Posted March 7, 2014 The "Case $BFFM_IUNKNOWN" section of your code:Note that $lParam is just $pText from line 153. To implement IFolderFilter $lParam must be a pointer to an interface that exposes IFolderFilterSite.$oShellFolder is not an IShellFolder interface as you can check with this piece of code:If IsObj( $oShellFolder ) Then ConsoleWrite( "$oShellFolder OK" & @CRLF ) Else ConsoleWrite( "$oShellFolder ERR" & @CRLF ) EndIfYou should definitely use a COM error handler while you are developing/testing. You can find one in the example for the ObjEvent function in the helpfile.To walk backwards through a PIDL use the functions ILFindLastID and ILRemoveLastID. To keep the original PIDL unchanged create a copy with ILClone. 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