Trancexx: Help needed re Com objects in FileSelectFolder UDF

4 posts in this topic

I'm in need of subtatial help with trancexx's FileSelectFolder UDF, if possible from the author herself.

That UDF uses COM objects derived from the system-standard file dialog (IFileDialog), which object is then somewhat modified to implement the specific features trancexx wanted. What I want to do is modify that COM object further to add two Radio Button groups to the dialog, and return their values to the caller.

Here's a rough example of what I think the modified FileSelectFolder2 code would have to approximate. Note that the string arguments containing all caps are from a C++ example provided by Microsoft.

; _MyModSelectFolder.au3
;.......script written by trancexx (trancexx at yahoo dot com)

; Donations to help me write more are very welcome. I can receive them via PayPal address: trancexx at yahoo dot com
; Thank you for the shiny stuff :kiss:

#include <GUIConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#Include <GuiButton.au3>
#include <Array.au3>
#include <Constants.au3>
#include <StaticConstants.au3>
#include <Misc.au3>
#include <String.au3>
#include <StringConstants.au3>
#include <File.au3>
#include <FileConstants.au3>
#include <ColorConstants.au3>
#include <GDIPlus.au3>
#include <GDIPlusConstants.au3>
#include <StructureConstants.au3>
#include <Date.au3>
#include <WinAPI.au3>

#include "ModStatusMessages.au3"


#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*);"

; Initiates a Browse For Folder dialog - new Windows style - if available. If not available old style gets invoked.
; Same parameters as built-in functions plus few more :P.

Func _MyModSelectFolder( $arg_PromptStr, $arg_RootFoldVal )

    Local $iFlag=0, $sInitialDir="", $hWindow=0, $iFlags=Default, $sButtonText=Default
    Local $sDialogText = $arg_PromptStr, $sRootDir = $arg_RootFoldVal
    Local $Lf_Stat, $Lf_RadioButtonListObjPtr
;~ Func FileSelectFolder2($sDialogText, $sRootDir, $iFlag = 0, $sInitialDir = "", $hWindow = 0, $iFlags = Default, $sButtonText = Default)
    Local $oIFileDialog = ObjCreateInterface($sCLSID_FileOpenDialog, $sIID_IFileOpenDialog, $tagIFileOpenDialog)
    If @error Then
        _MyUpdStatusMsg("_MyModSelectFolder() - ObjCreateInterface(FileDialog) failed")
        Return ""
    Local $Lf_DlgObjID_CustomizeObjPtr = $oIFileDialog.QueryInterface()
    If $Lf_DlgObjID_CustomizeObjPtr = 0 Then            ; Null return means error
        _MyUpdStatusMsg("_MyModSelectFolder() - $oIFileDialog.QueryInterface method failed")
        Return ""
    $Lf_Stat = $Lf_DlgObjID_CustomizeObjPtr.AddRadioButtonList("CONTROL_RADIOBUTTONLIST")
    If $Lf_Stat <> 0 Then                               ; Call failed
        _MyUpdStatusMsg("_MyModSelectFolder() - AddRadioButtonList method failed")
        Return ""
    $Lf_Stat = $Lf_DlgObjID_CustomizeObjPtr.SetControlState("CONTROL_RADIOBUTTONLIST, CDCS_VISIBLE | CDCS_ENABLED")
    If $Lf_Stat <> 0 Then                                   ; Failure
        _MyUpdStatusMsg("_MyModSelectFolder() - SetControlState method failed")
        Return ""
    $Lf_Stat = $Lf_DlgObjID_CustomizeObjPtr.AddControlItem("CONTROL_RADIOBUTTONLIST, CONTROL_RADIOBUTTONGroup1")
    If $Lf_Stat <> 0 Then                                   ; Failure
        _MyUpdStatusMsg("_MyModSelectFolder() - AddControlItem - RadioButtonGroup1 method failed")
        Return ""
    $Lf_Stat = $Lf_DlgObjID_CustomizeObjPtr.AddControlItem("CONTROL_RADIOBUTTONLIST, CONTROL_RADIOBUTTONGroup2")
    If $Lf_Stat <> 0 Then                                   ; Failure
        _MyUpdStatusMsg("_MyModSelectFolder() - AddControlItem - RadioButtonGroup2 method failed")
        Return ""
    $Lf_Stat = $Lf_DlgObjID_CustomizeObjPtr.SetSelectedControlItem("CONTROL_RADIOBUTTONLIST, CONTROL_RADIOBUTTON1")
    If $Lf_Stat <> 0 Then                                   ; Failure
        _MyUpdStatusMsg("_MyModSelectFolder() - AddControlItem - SetSelectedControlItem method failed")
        Return ""
;   Pick up from trancexx's UDF code
    If $sButtonText <> Default Then $oIFileDialog.SetOkButtonLabel($sButtonText)
    If $sRootDir = "" Then $sRootDir = @DesktopDir

    Local $pIDL = FSF_SHParseDisplayName($sRootDir)
    Local $oRoot = ObjCreateInterface(FSF_SHCreateShellItem($pIDL), $sIID_IShellItem, $tagIShellItem)
    If @error Then
        _MyUpdStatusMsg("_MyModSelectFolder() - ObjCreateInterface(FSF_SHCreateShellItem) #2 Failed!")
        Return ""
;~      Return FileSelectFolder($sDialogText, $sRootDir, $iFlag, $sInitialDir, $hWindow)

    Local Const $FOS_PICKFOLDERS = 0x20
    if $iFlags = Default Then $iFlags = $FOS_PICKFOLDERS
    $oIFileDialog.Show($hWindow) ; Tada mtfk!

    Local $pShellItemArray
    Local $oShellItemArray = ObjCreateInterface($pShellItemArray, $sIID_IShellItemArray, $tagIShellItemArray)
    If @error Then Return SetError(1, 0, "")
    Local $iCount
    Local $pShellItem, $oIShellItem, $pName, $sName
    Local Const $S_OK = 0
    Local Const $SIGDN_DESKTOPABSOLUTEEDITING = 0x8004c000, $SIGDN_FILESYSPATH = 0x80058000
;   For _MyModSelectFolder, the following code must be modified to return both radio button group's choice status
    For $i = 0 To $iCount - 1
        $oShellItemArray.GetItemAt($i, $pShellItem)
        $oIShellItem = ObjCreateInterface($pShellItem, $sIID_IShellItem, $tagIShellItem)
        If @error Then ContinueLoop
        If $oIShellItem.GetDisplayName($SIGDN_FILESYSPATH, $pName) <> $S_OK Then
            If $oIShellItem.GetDisplayName($SIGDN_DESKTOPABSOLUTEEDITING, $pName) <> $S_OK Then Return SetError(2, 0, "")
        $sName &= DllStructGetData(DllStructCreate("wchar[" & FSF_StringLenW($pName) + 1 & "]", $pName), 1) & "|"
    SetError(0, 0, StringTrimRight($sName, 1))
    Return StringTrimRight($sName, 1)

; Few helper functions down below...
Func FSF_SHParseDisplayName($sPath)
    Local $aCall = DllCall("shell32.dll", "long", "SHParseDisplayName", "wstr", $sPath, "ptr", 0, "ptr*", 0, "ulong", 0, "ulong*", 0)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[3]
Func FSF_SHCreateShellItem($pPIDL)
    Local $aCall = DllCall("shell32.dll", "long", "SHCreateShellItem", "ptr", 0, "ptr", 0, "ptr", $pPIDL, "ptr*", 0)
    If @error Or $aCall[0] Then Return SetError(1, 0, 0)
    Return $aCall[4]
Func FSF_CoTaskMemFree($pMemory)
    DllCall("ole32.dll", "none", "CoTaskMemFree", "ptr", $pMemory)
    If @error Then Return SetError(1, 0, 0)
    Return 1
Func FSF_StringLenW($vString)
    Local $aCall = DllCall("kernel32.dll", "int", "lstrlenW", "struct*", $vString)
    If @error Then Return SetError(1, 0, 0)
    Return $aCall[0]
Func _MyUpdStatusMsg( $arg_Msg )
    Local $Lf_MsgLineAra = StringSplit( $arg_Msg, @CR, $STR_ENTIRESPLIT )
    If @error = 1 Then              ; If no crlf delimiters found...
        StatusMsgs_WriteLine( $arg_Msg )
        Local $Lf_MsgCount = $Lf_MsgLineAra[0]
        For $i = 1 To $Lf_MsgCount
            StatusMsgs_WriteLine( StringStripCR($Lf_MsgLineAra[$i]) )


Obviously, this code must be fleshed out considerably, for which I am seeking assistance.  For example, what data structures are used in these COM object calls, such as the Radio Button List Control ("CONTROL_RADIOBUTTONLIST"), and how do I create and populate them?  Am I missing any method calls I need?  Etc, etc...

I would be endlessly grateful for guidance and coding assistance!


Share this post

Link to post
Share on other sites
39 minutes ago, Jfish said:

You can tag people in your posts like this @trancexx.  

Thought that may be useful for your bat-signal post ;)


Hey, thanks for the helpful tip, jfish!


Share this post

Link to post
Share on other sites

I don't have time to program right now but here is a C++ sample https://msdn.microsoft.com/en-us/library/windows/desktop/bb776913(v=vs.85).aspx



Share this post

Link to post
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

  • Similar Content

    • UEZ
      By UEZ
      Link and example: FrameGrabber.dll 
      What about my question regarding returning a bitmap handle or bitmap data rather than saving the grabbed frame to disk?
      Actually I would talk about VScript because I'm curious but Jon doesn't want it but can you show me the code please? You said it is similar to AU3 code. I want to understand how you did it.
    • sanulevan
      By sanulevan

      i install the software NXPowerlite in my C:\Program Files (x86)\NXPowerLite folder,
      please give a sample code for running this software without using run,winwaitactive ,etc(using com obj).