Jump to content

Recommended Posts

Posted

in this topic:

there is a reference to this function, using the "old style" by DLL call:

Func _FileSelectFolder ($title, $root = 0, $flags = 0, $hwnd = 0)
    Local $ret, $pidl, $res = ''   
    Local $ubi = DllStructCreate ("hwnd;ptr;ptr;ptr;int;ptr;ptr;int") 
    Local $utl = DllStructCreate ("char[512]") 
    Local $urs = DllStructCreate ("char[260]") 
    Local $ulf = BitOR (BitShift(BitAnd ($flags,1),-9), _ 
        BitShift(BitAnd ($flags,2),-5), _
        BitShift(BitAnd ($flags,4),-2))    
    DllStructSetData ($utl, 1, $title)
    DllStructSetData ($ubi, 1, $hwnd)
    DllStructSetData ($ubi, 3, DllStructGetPtr($urs))
    DllStructSetData ($ubi, 4, DllStructGetPtr($utl))
    DllStructSetData ($ubi, 5, $ulf)
    $ret = DllCall ("shell32.dll", "ptr", "SHGetSpecialFolderLocation", _
        "int", 0 , _
        "int", $root , _
        "ptr", DllStructGetPtr($ubi, 2))
    If $ret[0] Then Return $res
    $pidl = DllCall ("shell32.dll", "ptr", "SHBrowseForFolder", "ptr", DllStructGetPtr ($ubi))
    If $pidl[0] Then
        $ret = DllCall ("shell32.dll", "int", "SHGetPathFromIDList", _
            "ptr", $pidl[0], _
            "ptr", DllStructGetPtr ($urs))
        If $ret[0] Then $res = DllStructGetData ($urs, 1)
        DllCall ("ole32.dll", "int", "CoTaskMemFree", "ptr", $pidl[0]) 
    EndIf
    DllCall ("ole32.dll", "int", "CoTaskMemFree", "ptr", DllStructGetData ($ubi, 2))
    Return $res
EndFunc

this function accepts the "root" dir as an integer, not a string (it calls the SHBrowseForFolder function, which accepts the BROWSEINFO struct, which holds the folder as an integer). this is a complete mystery to me; however, for Windows, that apparently makes perfect sense. :huh2:

i can't understand how this function can accept any root dir other than the default. can anyone shed some light on that?

Signature - my forum contributions:

Spoiler

UDF:

LFN - support for long file names (over 260 characters)

InputImpose - impose valid characters in an input control

TimeConvert - convert UTC to/from local time and/or reformat the string representation

AMF - accept multiple files from Windows Explorer context menu

DateDuration -  literal description of the difference between given dates

Apps:

Touch - set the "modified" timestamp of a file to current time

Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes

SPDiff - Single-Pane Text Diff

 

Posted

I never did much with the Shell Namespace because I didn't have to and it is a pita. :)

 

This site may shed some light on it:

https://msdn.microsoft.com/en-us/library/windows/desktop/cc144090(v=vs.85).aspx#unknown_13653

 

The confusion may be that the PIDL is like an integer type that is used as a pointer.  You might try to find examples in a different programming language.  Maybe something in C# or C++ on the Code Project site.

 

Posted (edited)

following MSDN links i came across this: SHParseDisplayName

Translates a Shell namespace object's display name into an item identifier list and returns the attributes of the object. This function is the preferred method to convert a string to a pointer to an item identifier list (PIDL). 

i tried to implement it, and failed miserably. this is my attempt:

Func _FileSelectFolder($title, $sRoot = '', $flags = 0, $hwnd = 0)
    Local $ret, $pidl, $res = ''
    Local $ubi = DllStructCreate("hwnd;ptr;ptr;ptr;int;ptr;ptr;int")
    Local $utl = DllStructCreate("char[512]")
    Local $urs = DllStructCreate("char[260]")
    Local $ulf = BitOR(BitShift(BitAND($flags, 1), -9), _
            BitShift(BitAND($flags, 2), -5), _
            BitShift(BitAND($flags, 4), -2))
    DllStructSetData($utl, 1, $title)
    DllStructSetData($ubi, 1, $hwnd)
    DllStructSetData($ubi, 3, DllStructGetPtr($urs))
    DllStructSetData($ubi, 4, DllStructGetPtr($utl))
    DllStructSetData($ubi, 5, $ulf)


    If $sRoot = '' Then
        $ret = DllCall("shell32.dll", "ptr", "SHGetSpecialFolderLocation", _
                "int", 0, _
                "int", 0, _
                "ptr", DllStructGetPtr($ubi, 2))
        If $ret[0] Then Return $res
    Else

        ; >>>>> how to call SHParseDisplayName so that the $ubi struct will contain the PIDL in element #3 ?
        $ret = DllCall("shell32.dll", "long", "SHParseDisplayName", _
                'ptr', Ptr($sRoot), _
                'ptr', Null, _
                'ptr', DllStructGetPtr($ubi, 2), _
                'ptr', Null, _
                'ptr', Null)
        DllStructSetData($ubi, 2, $ret[3])
        ; >>>>>

        If $ret[0] Then Return $res
    EndIf


    $pidl = DllCall("shell32.dll", "ptr", "SHBrowseForFolder", "ptr", DllStructGetPtr($ubi))
    If $pidl[0] Then
        $ret = DllCall("shell32.dll", "int", "SHGetPathFromIDList", _
                "ptr", $pidl[0], _
                "ptr", DllStructGetPtr($urs))
        If $ret[0] Then $res = DllStructGetData($urs, 1)
        DllCall("ole32.dll", "int", "CoTaskMemFree", "ptr", $pidl[0])
    EndIf
    DllCall("ole32.dll", "int", "CoTaskMemFree", "ptr", DllStructGetData($ubi, 2))
    Return $res
EndFunc   ;==>_FileSelectFolder

i redefined the parameter to accept a string (empty string by default). if the string is empty, it follows the original logic to calculate the PIDL of the "desktop". this still works. but if it's not empty, i try to call SHParseDisplayName to calculate the PIDL. as i understand, that PIDL should be placed into the DLL struct that is later passed to SHBrowseForFolder (named $ubi here), as the 3rd field of the struct. i can't get that to work - see the section marked by  ; >>>>>  in the code above. what am i doing wrong?

Edited by orbs

Signature - my forum contributions:

Spoiler

UDF:

LFN - support for long file names (over 260 characters)

InputImpose - impose valid characters in an input control

TimeConvert - convert UTC to/from local time and/or reformat the string representation

AMF - accept multiple files from Windows Explorer context menu

DateDuration -  literal description of the difference between given dates

Apps:

Touch - set the "modified" timestamp of a file to current time

Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes

SPDiff - Single-Pane Text Diff

 

Posted
Posted

thank you LarsJ, i'll look into that (and i'll keep in mind to look in the WinAPI UDF if i ever bump into a DLL call).

Signature - my forum contributions:

Spoiler

UDF:

LFN - support for long file names (over 260 characters)

InputImpose - impose valid characters in an input control

TimeConvert - convert UTC to/from local time and/or reformat the string representation

AMF - accept multiple files from Windows Explorer context menu

DateDuration -  literal description of the difference between given dates

Apps:

Touch - set the "modified" timestamp of a file to current time

Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes

SPDiff - Single-Pane Text Diff

 

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
  • Recently Browsing   0 members

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