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"

#include-once

;===============================================================================
#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 ""
    EndIf
;
    Local $Lf_DlgObjID_CustomizeObjPtr = $oIFileDialog.QueryInterface()
    If $Lf_DlgObjID_CustomizeObjPtr = 0 Then            ; Null return means error
        _MyUpdStatusMsg("_MyModSelectFolder() - $oIFileDialog.QueryInterface method failed")
        Return ""
    EndIf
;
    $Lf_Stat = $Lf_DlgObjID_CustomizeObjPtr.AddRadioButtonList("CONTROL_RADIOBUTTONLIST")
    If $Lf_Stat <> 0 Then                               ; Call failed
        _MyUpdStatusMsg("_MyModSelectFolder() - AddRadioButtonList method failed")
        Return ""
    EndIf
;
    $Lf_Stat = $Lf_DlgObjID_CustomizeObjPtr.SetControlState("CONTROL_RADIOBUTTONLIST, CDCS_VISIBLE | CDCS_ENABLED")
    If $Lf_Stat <> 0 Then                                   ; Failure
        _MyUpdStatusMsg("_MyModSelectFolder() - SetControlState method failed")
        Return ""
    EndIf
;
    $Lf_Stat = $Lf_DlgObjID_CustomizeObjPtr.AddControlItem("CONTROL_RADIOBUTTONLIST, CONTROL_RADIOBUTTONGroup1")
    If $Lf_Stat <> 0 Then                                   ; Failure
        _MyUpdStatusMsg("_MyModSelectFolder() - AddControlItem - RadioButtonGroup1 method failed")
        Return ""
    EndIf
;
    $Lf_Stat = $Lf_DlgObjID_CustomizeObjPtr.AddControlItem("CONTROL_RADIOBUTTONLIST, CONTROL_RADIOBUTTONGroup2")
    If $Lf_Stat <> 0 Then                                   ; Failure
        _MyUpdStatusMsg("_MyModSelectFolder() - AddControlItem - RadioButtonGroup2 method failed")
        Return ""
    EndIf
;
    $Lf_Stat = $Lf_DlgObjID_CustomizeObjPtr.SetSelectedControlItem("CONTROL_RADIOBUTTONLIST, CONTROL_RADIOBUTTON1")
    If $Lf_Stat <> 0 Then                                   ; Failure
        _MyUpdStatusMsg("_MyModSelectFolder() - AddControlItem - SetSelectedControlItem method failed")
        Return ""
    EndIf
;
;
;   Pick up from trancexx's UDF code
;
    $oIFileDialog.SetTitle($sDialogText)
    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)
    EndIf
    FSF_CoTaskMemFree($pIDL)

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

    Local $pShellItemArray
    $oIFileDialog.GetResults($pShellItemArray)
    Local $oShellItemArray = ObjCreateInterface($pShellItemArray, $sIID_IShellItemArray, $tagIShellItemArray)
    If @error Then Return SetError(1, 0, "")
    Local $iCount
    $oShellItemArray.GetCount($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, "")
        EndIf
        $sName &= DllStructGetData(DllStructCreate("wchar[" & FSF_StringLenW($pName) + 1 & "]", $pName), 1) & "|"
        FSF_CoTaskMemFree($pName)
    Next
    SetError(0, 0, StringTrimRight($sName, 1))
    Return StringTrimRight($sName, 1)
EndFunc

; 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]
EndFunc
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]
EndFunc
Func FSF_CoTaskMemFree($pMemory)
    DllCall("ole32.dll", "none", "CoTaskMemFree", "ptr", $pMemory)
    If @error Then Return SetError(1, 0, 0)
    Return 1
EndFunc
Func FSF_StringLenW($vString)
    Local $aCall = DllCall("kernel32.dll", "int", "lstrlenW", "struct*", $vString)
    If @error Then Return SetError(1, 0, 0)
    Return $aCall[0]
EndFunc
;
;
;
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 )
    Else
        Local $Lf_MsgCount = $Lf_MsgLineAra[0]
        For $i = 1 To $Lf_MsgCount
            StatusMsgs_WriteLine( StringStripCR($Lf_MsgLineAra[$i]) )
        Next
    EndIf
EndFunc

 

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!

 

Link to comment
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
 Share

×
×
  • Create New...