Jump to content

Trancexx: Help needed re Com objects in FileSelectFolder UDF

Recommended Posts


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).

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.