#include-once ; #INDEX# ============================================================================================================ ; Title .........: ChooseFileFolder ; AutoIt Version : 3.3.10 + ; Language ......: English ; Description ...: Allows selection of single or multiple files and/or folders ; Remarks .......: If the script already has WM_NOTIFY or WM_COMMAND handlers then call the relevant _CFF_WM_####_Handler ; function from within them ; Author ........: Melba23 ; Modified ......; Thanks to guinness for help with the #*@#*%# Struct !!!! ; ==================================================================================================================== ;#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7 ; #INCLUDES# ========================================================================================================= #include #include #include #include ; =============================================================================================================================== ; #GLOBAL VARIABLES# ================================================================================================= Global $g_cCFF_Expand_Dummy, _ ; Branch expansion event $g_hCFF_Expand_Handle, _ ; Expanded item handle $g_cCFF_Expand_CID, _ ; Expanded item ControlID $g_cCFF_Select_Dummy, _ ; Item selection event (checkbox on native treeView) $g_hCFF_Select_Handle, _ ; Selected item handle $g_cCFF_Click_Dummy, _ ; Item click event (checkbox on UDF TreeView) $g_cCFF_DblClk_Dummy, _ ; Expansion or selection $g_cCFF_Esc_Dummy, _ ; Escape or Cancel button $g_cCFF_Refresh_Dummy, _ ; Refresh drive list $g_hCFF_TreeView, _ ; Active TreeView handle $g_hCFF_List = 9999, _ ; Active list handle - with placeholder $g_bCFF_TV_Active = True, _ ; Flag to determine whether TreeView or list is active $g_bCFF_AutoExpand, _ ; Flag for autoexpansion $g_aCFF_PreCheck = "", _ ; Prechecked item list $g_aCFF_PreCheckRetain = "", _ ; Copy of precheck list if not volatile $g_bCFF_RetainSel, _ ; Flag for delete/retain previous selection when refreshing $g_aCFF_Checked_Retain ; Retained selected checkbox array ; Enums for the Local $aFlags array elements Global Enum $g_eCFF_ShowExt, $g_eCFF_HideHS, $g_eCFF_BothSelectable, $g_eCFF_DuplicatesAllowed, _ $g_eCFF_FileScroll, $g_eCFF_ShowSplash, $g_eCFF_OnlyReturnDeepest, $g_eCFF_AllowRefresh, $g_eCFF_FlagMax ; #CURRENT# ========================================================================================================== ; _CFF_Choose: Creates a dialog to chose single or multiple files or folders ; _CFF_Embed: Creates a folder tree within an existing treeview and optional list ; _CFF_Refresh; Re-reads drives to refresh TreeView - also toggles delete/retain of existing selections ; _CFF_SetPreCheck: Sets a list of files/folders which will be checked when expanded ; _CFF_RegMsg: Registers WM_NOTIFY for TreeView doubleclick and item expansion and WM_COMMAND for list focus ; _CFF_WM_NOTIFY_Handler: WM_NOTIFY handler - TreeView doubleclick, checkbox selection, item expansion - Cancel split button ; _CFF_WM_COMMAND_Handler: WM_COMMAND handler - List getting focus ; ==================================================================================================================== ; #INTERNAL_USE_ONLY#================================================================================================= ; __CFF_List_Drives: Creates lists of available drives if no path is set ; __CFF_Fill_Combo: Creates and fills a combo for drive selection ; __CFF_Fill_Drives: Fills a TreeView with ready drives ; __CFF_Fill_Branch: Fills a TreeView branch with folders and files on expansion ; __CFF_AutoExpand: Expand tree to defined folder on start ; __CFF_File_Visible: Ensure files visible if selecting files only and displaying both files and folders ; __CFF_Check_Display: Checks for valid Display parameter ; __CFF_Verify_PreCheck: Checks for valid pre-check array elements ; __CFF_Check_Selection: Checks selection is valid ; __CFF_ParseTV: Creates array of current TreeView checkbox state ; __CFF_Checked_List: Creates array of checked items to be retained during a refresh ; __CFF_Adjust_Parents: Adjusts parent checkboxes ; __CFF_Adjust_Children: Adjusts children to parent checked state ; __CFF_List_Add: Adds item to return list ; __CFF_List_Del: Deletes item from return list ; __CFF_Dropdown_Menu: Creates menu for Cancel split button ; ==================================================================================================================== ; #FUNCTION# ========================================================================================================= ; Name...........: _CFF_Choose ; Description ...: Creates a dialog to chose single or multiple files or folders ; Syntax.........: _CFF_Choose ($sTitle, [$iW = 1, [$iH = 1, [$iX = -1, [$iY = -1, [$sRoot = "", [$s_Mask = "", [$iDisplay = 0, [$iMultiple = True, [$hParent = 0]]]]]]]]]) ; Parameters ....: $sTitle - Title of dialog - only necessary parameter! ; $iW, $iH - Width, Height parameters for dialog (Default and minimum = 250 x 300). Set negative for resizable dialog ; $iX, $iY - Left, Top parameters for dialog (Default = centred) ; $sRoot - Valid path = Tree to display ; If folder, contents of folder are displayed ; If filename, contents of parent folder are displayed with the file highlighted ; To permit drive selection: ; "" (default) = All ready drives shown ; List of drive letters (e.g. "cde") = Limit display to these drives if ready ; Add "|drive letter" (e.g. "cde|d" or "|d") = Highlight and expand specified drive tree on opening ; or "|folder path" (e.g. "cde|d:\folder) = Highlight specified folder (add "\" to expand folder) ; Add "|c" (e.g. cde||c" or "|d|c" or "||c) = Display drives in separate combo not treeview ; $sMask - Filter for result. Multiple filters must be separated by ";" ; Use "|" to separate 3 possible sets of filters: "Include|Exclude|Exclude_Folders" ; Include = Files/Folders to include (default = "*" [all]) ; Exclude = Files/Folders to exclude (default = "" [none]) ; Exclude_Folders = only used if the basic $iDisplay = 0 to exclude defined folders (default = "" [none]) ; $iDisplay - Determine what is displayed in the tree ; 0 - Entire folder tree and all matching files within folders - only files can be selected (default) ; - Double clicking folders will only expand/contract contents, NOT select (see option 16 below) ; 1 - All matching files within the specified folder - subfolders are not displayed ; - Doubleclick will select file ; 2 - Entire folder tree only - no files ; - Doubleclick will select folder ; - All modes: "Select/Add" button will always select highlighted element if valid ; {ENTER} key: Single selection - select highlighed item ; Multiple selections - returns list ; + 4 - Do not display Hidden files/folders ; + 8 - Do not display System files/folders ; + 16 - Both files and folders selectable if basic $iDisplay set to 0 - folders have trailing \ ; + 32 - Allow duplicate selections when clicking ; + 64 - Hide file extensions (only valid if file mask specifies a single extension) ; + 128 - Scroll to first file in folder - only valid if basic $iDisplay set to 0 ; + 256 - Display splashscreens when searching for drives and autoexpanding tree ; + 512 - When using checkboxes only return deepest items on path - default return all checked items ; + 1024 - Allow drive list refresh ; $iMultiple - 0 or non-numeric = Only 1 selection (default) ; -1 = Multiple selections using checkboxes ; 10-50 = Multiple selections added to list. List size 10-50% of dialog ; Other numeric = Multiple selections added to list. List size set to 20% of dialog ; $hParent - Handle of GUI calling the dialog, (default = 0 - no parent GUI) ; Requirement(s).: v3.3 + ; Return values .: Success: String containing selected items - multiple items delimited by "|" ; Failure: Returns "" and sets @error as follows: ; 1 = Invalid $sRoot parameter ; @extended = 1 - Path does not exist ; 2 - Invalid drive list ; 2 = Invalid $iDisplay parameter ; 3 = Invalid $hParent parameter ; 4 = Dialog creation failure ; 5 = Cancel button, {ESCAPE} or GUI [X] pressed ; Author ........: Melba23 ; Modified ......: ; Remarks .......: - Multiple selections: ; If using list: ; Press "Add" or doubleclick in treeview to add item to list ; Press "Delete" to delete selected item from treeview or list ; If using checkboxes: ; Use checkboxes to select items ; Pressing Ctrl when (un)checking sets all children to same state ; Pressing Alt when (un)checking sets parents to same state (uncheck if no other checked items on same path) ; Both cases: ; Press "Return" button or "{ENTER}" key when selection ended ; Press "Cancel" button or "{ESCAPE}" key to abandon selection ; - If drive refresh allowed, Cancel button has dropdown style with "Refresh" selection ; _CFF_Refresh function can also refresh drive list via HotKey ; Example........: Yes ;===================================================================================================================== Func _CFF_Choose($sTitle, $iW = 1, $iH = 1, $iX = -1, $iY = -1, $sRoot = "", $sMask = "*", $iDisplay = 0, $iMultiple = 0, $hParent = 0) Local Const $iFixed = 0x80C80000 ; BitOR($WS_POPUPWINDOW, $WS_CAPTION) Local Const $iResizable = 0x80CC0000 ; BitOR($WS_POPUPWINDOW, $WS_CAPTION, $WS_SIZEBOX) Local Const $iComposite = 0x02000000 ; $WS_EX_COMPOSITED Local $bCombo = False, $bDefFolder_Open = False Local $sDrives = "", $sDefDrive = "", $sDefFolder_Check, $sDefFolder, $sDefFile Local $iStyle = $iFixed, $iExStyle = 0, $iRedraw_Count = 5, $bNoFolderCheck = False Local $aAll_Drives[1] = [0], $aNetwork_Drives[1] = [0], $aFill_Ret[3], $aTVCheckData Local $aFlags[$g_eCFF_FlagMax] = [True, 0, False, False, False, False, False, False] ; Set default global value $g_bCFF_AutoExpand = False ; Check size If $iW = Default Then $iW = 1 EndIf If $iH = Default Then $iH = 1 EndIf ; Set dialog resizing style If $iW < 0 Or $iH < 0 Then $iStyle = $iResizable $iExStyle = $iComposite $iW = Abs($iW) $iH = Abs($iH) EndIf ; Check position If $iX = Default Then $iX = -1 EndIf If $iY = Default Then $iY = -1 EndIf ; Check path Switch $sRoot Case "", Default $sRoot = "" Case Else ; If a path If FileExists($sRoot) Then ; Check if file or folder If StringInStr(FileGetAttrib($sRoot), "D") Then ; Add trailing \ if needed If StringRight($sRoot, 1) <> "\" Then $sRoot &= "\" EndIf Else $sDefFile = StringRegExpReplace($sRoot, "^.*\\", "") $sRoot = StringRegExpReplace($sRoot, "(^.*\\)(.*)", "\1") EndIf Else ; Split to look for eventual drive|default|combo info Local $aSplit = StringSplit($sRoot, "|") If $aSplit[0] < 4 Then ; Check required drive list If Not StringRegExp($aSplit[1], "(?i)^[a-z]*$") Then ; Reset precheck array as required $g_aCFF_PreCheck = $g_aCFF_PreCheckRetain Return SetError(1, 2, "") EndIf ; And store $sDrives = StringUpper($aSplit[1]) ; Check for default drive If $aSplit[0] > 1 Then $sDefDrive = StringUpper(StringLeft($aSplit[2], 1)) ; Check if default in drive list If $sDrives And (Not StringInStr($sDrives, $sDefDrive)) Then ; Clear if not $sDefDrive = "" Else ; Add colon If $sDefDrive Then $sDefDrive &= ":" EndIf EndIf ; Is it a valid folder path? If FileExists($aSplit[2]) And StringInStr(FileGetAttrib($aSplit[2]), "D") Then $sDefFolder = $aSplit[2] ; Check if trailing backslash If StringRight($sDefFolder, 1) = "\" Then ; Set flag $bDefFolder_Open = True ; Remove the trailing backslash $sDefFolder = StringTrimRight($sDefFolder, 1) EndIf ; Replace backslashes for comparison when expanding $sDefFolder_Check = StringReplace($sDefFolder, "\", "|") EndIf EndIf ; Use combo for drive choice? If $aSplit[0] = 3 And $aSplit[3] = "C" Then $bCombo = True EndIf ; Clear root parameter to show drive choice required $sRoot = "" Else ; Reset precheck array as required $g_aCFF_PreCheck = $g_aCFF_PreCheckRetain ; Not valid path or drive list Return SetError(1, 1, "") EndIf EndIf EndSwitch ; Create drive lists if no root set Local $iAll_Error = 0, $iNetwork_Error = 0 If $sRoot = "" Then __CFF_List_Drives($sDrives, $aAll_Drives, $aNetwork_Drives, $iAll_Error, $iNetwork_Error) If $iAll_Error Then Local $aAll_Drives[1] = [0] EndIf If $iNetwork_Error Then Local $aNetwork_Drives[1] = [0] EndIf EndIf ; Check Mask If $sMask = Default Or $sMask = "" Then $sMask = "*" EndIf ; Extract File mask (needed for hide extension code) Local $aMaskSplit = StringSplit($sMask, "|") Local $sFile_Mask = $aMaskSplit[1] ; Check Display parameter If $iDisplay = Default Then $iDisplay = 0 EndIf $iDisplay = __CFF_Check_Display($iDisplay, $sFile_Mask, $aFlags) If @error Then ; Reset precheck array as required $g_aCFF_PreCheck = $g_aCFF_PreCheckRetain Return SetError(2, 0, "") EndIf ; Verify precheck list if set If IsArray($g_aCFF_PreCheck) Then __CFF_Verify_PreCheck($g_aCFF_PreCheck, $iDisplay, $aFlags[$g_eCFF_BothSelectable]) EndIf ; Check selection type and list size Local $bSingle_Sel = False, $bCheckBox = False, $iList_Percent = .2 If $iMultiple = Default Then $iMultiple = 0 Switch Number($iMultiple) Case 0, Default $bSingle_Sel = True Case 10 To 50 $iList_Percent = .01 * $iMultiple Case -1 $bCheckBox = True If $iDisplay = 3 Then $iDisplay = 2 ; Remove possible "selection on doubleclick" EndSwitch ; Check if checkboxes required If $iMultiple = -1 Then ; Check if folder checkboxes should be hidden - only files selectable and no prechecks If $iDisplay = 0 And Not ($aFlags[$g_eCFF_BothSelectable]) And Not (IsArray($g_aCFF_PreCheck)) Then $bNoFolderCheck = True EndIf EndIf ; Check parent Switch $hParent Case Default $hParent = 0 Case 0 Case Else If Not IsHWnd($hParent) Then ; Reset precheck array as required $g_aCFF_PreCheck = $g_aCFF_PreCheckRetain Return SetError(3, 0, "") EndIf EndSwitch ; Check for width and height minima If $bSingle_Sel Then If $iW < 250 Then $iW = 250 Else If $iW < 350 Then $iW = 350 EndIf If $iH < 300 Then $iH = 300 ; Set button size Local $iButton_Width = Int(($iW - 50) / 4) If $iButton_Width > 80 Then $iButton_Width = 80 If $iButton_Width < 50 Then $iButton_Width = 50 ; Create Dialog Local $hCFF_Win = GUICreate($sTitle, $iW, $iH, $iX, $iY, $iStyle, $iExStyle, $hParent) If @error Then ; Reset precheck array as required $g_aCFF_PreCheck = $g_aCFF_PreCheckRetain Return SetError(4, 0, "") EndIf GUISetBkColor(0xCECECE) If $aFlags[$g_eCFF_ShowSplash] Then ; Show splash if dialog display delay likely - multiple drives or autoexpansion Local $sMsg = "" If Not $sRoot And Not $sDefFolder Then $sMsg = "Detecting drives..." ElseIf $sDefFolder Then $sMsg = "Expanding tree..." ; Prevent user input BlockInput(1) EndIf If $sMsg Then Local $aPos = WinGetPos($hCFF_Win) SplashTextOn("ChooseFileFolder", $sMsg, $iW - 100, 100, $aPos[0] + 50, $aPos[1] + 100) EndIf EndIf ; Declare variables Local $cCan_Button, $cSel_Button = 9999, $cAdd_Button = 9999, $cDel_Button = 9999, $cRet_Button = 9999 Local $cTreeView = 9999, $cList = 9999, $cDrive_Combo = 9999 Local $sCurrDrive = "", $sSelectedPath, $iList_Height, $iTV_Height, $sAddFile_List = "" Local $cItem, $hItem ; Create buttons If $bSingle_Sel Then $cSel_Button = GUICtrlCreateButton("Select", $iW - ($iButton_Width + 10), $iH - 40, $iButton_Width, 30) Else If Not $bCheckBox Then $cAdd_Button = GUICtrlCreateButton("Add", 10, $iH - 40, $iButton_Width, 30) $cDel_Button = GUICtrlCreateButton("Delete", $iButton_Width + 20, $iH - 40, $iButton_Width, 30) EndIf $cRet_Button = GUICtrlCreateButton("Return", $iW - ($iButton_Width + 10), $iH - 40, $iButton_Width, 30) EndIf ; Use dropdown style for Cancel button if drive list to be displayed to give refresh selection Local $iCancelStyle = (($aFlags[$g_eCFF_AllowRefresh] And ((Not FileExists($sRoot)) Or $bCombo)) ? (0x0000000C) : (-1)) $cCan_Button = GUICtrlCreateButton("Cancel", $iW - ($iButton_Width + 10) * 2, $iH - 40, $iButton_Width, 30, $iCancelStyle) Local $cRet_Dummy = GUICtrlCreateDummy() ; fires on ENTER $g_cCFF_Esc_Dummy = GUICtrlCreateDummy() ; fires on ESC ; Set accel keys Local $aAccelKeys[2][2] = [["{ENTER}", $cRet_Dummy], ["{ESC}", $g_cCFF_Esc_Dummy]] GUISetAccelerators($aAccelKeys) ; Create controls Local $iOffset = 30 ; Offset if combo used If $bSingle_Sel Then If $bCombo Then ; Combo and TV ; Create and fill Combo $cDrive_Combo = __CFF_Fill_Combo($iW, $sDrives, $sDefDrive, $cDrive_Combo) Else ; TV only ; No offset $iOffset = 0 EndIf ; Create TV $cTreeView = GUICtrlCreateTreeView(10, 10 + $iOffset, $iW - 20, $iH - 60 - $iOffset) Else If $bCombo Then ; Combo and TV ; Create and fill Combo $cDrive_Combo = __CFF_Fill_Combo($iW, $sDrives, $sDefDrive, $cDrive_Combo) Else ; TV only ; No offset $iOffset = 0 EndIf If $bCheckBox Then ; Create TV $cTreeView = GUICtrlCreateTreeView(10, 10 + $iOffset, $iW - 20, $iH - 60 - $iOffset, BitOR($GUI_SS_DEFAULT_TREEVIEW, $TVS_CHECKBOXES)) Else ; Calculate control heights $iList_Height = Int(($iH - 60 - $iOffset) * $iList_Percent) If $iList_Height < 40 Then $iList_Height = 40 EndIf $iTV_Height = $iH - $iList_Height - 60 - $iOffset ; Create TV $cTreeView = GUICtrlCreateTreeView(10, 10 + $iOffset, $iW - 20, $iTV_Height) ; Create List $cList = GUICtrlCreateList("", 10, 10 + $iOffset + $iTV_Height, $iW - 20, $iList_Height, 0x00A00101) ; BitOR($WS_BORDER, $WS_VSCROLL, $LBS_NOINTEGRALHEIGHT, $LBS_NOTIFY) EndIf EndIf $g_cCFF_Expand_Dummy = GUICtrlCreateDummy() ; Fires when [+] clicked $g_cCFF_Select_Dummy = GUICtrlCreateDummy() ; Fires when item checked $g_cCFF_DblClk_Dummy = GUICtrlCreateDummy() ; Fires on DblClk $g_cCFF_Esc_Dummy = GUICtrlCreateDummy() ; Fires on Escape $g_cCFF_Refresh_Dummy = GUICtrlCreateDummy() ; Fires on drive refresh Local $cRedraw_Dummy = GUICtrlCreateDummy() ; Fires to redraw TreeViw if auto-expand fails ; Set Global values for handler checks $g_hCFF_TreeView = GUICtrlGetHandle($cTreeView) $g_hCFF_List = GUICtrlGetHandle($cList) ; Set resizing if required If $iStyle = $iResizable Then GUICtrlSetResizing($cTreeView, 2 + 4 + 32) ; $GUI_DOCKTOP + $GUI_DOCKLEFT + $GUI_DOCKRIGHT GUICtrlSetResizing($cList, 2 + 4) ; $GUI_DOCKLEFT + $GUI_DOCKRIGHT GUICtrlSetResizing($cAdd_Button, 2 + 64) ; $GUI_DOCKLEFT + $GUI+DOCKBOTTOM GUICtrlSetResizing($cDel_Button, 8 + 64) ; $GUI_DOCKHCENTER + $GUI+DOCKBOTTOM GUICtrlSetResizing($cCan_Button, 8 + 64) ; $GUI_DOCKHCENTER + $GUI+DOCKBOTTOM GUICtrlSetResizing($cSel_Button, 4 + 64) ; $GUI_DOCKRIGHT + $GUI+DOCKBOTTOM GUICtrlSetResizing($cRet_Button, 4 + 64) ; $GUI_DOCKRIGHT + $GUI+DOCKBOTTOM EndIf ; Hide dialog until tree drawing complete WinSetTrans($hCFF_Win, "", 1) ; Must be 1 as 0 = hidden ; Display dialog so that autoexpansion can occur if required GUISetState() ; Force OnTop - near invisible can be hidden WinSetOnTop($hCFF_Win, "", 1) ; Set required default drive if required If $sDefDrive Then If $bCombo Then ; Set default drive as root $sRoot = $sDefDrive & "\" ; Show in combo GUICtrlSetData($cDrive_Combo, $sDefDrive) EndIf EndIf ; Fill tree If $sRoot Then ; If root folder specified then fill TV $aFill_Ret = __CFF_Fill_Branch($cTreeView, $cTreeView, $sRoot, $iDisplay, $sMask, $aFlags[$g_eCFF_ShowExt], $aFlags[$g_eCFF_HideHS], $aNetwork_Drives, $aFlags[$g_eCFF_OnlyReturnDeepest], $bNoFolderCheck) Else If $bCombo Then __CFF_Fill_Combo($iW, $sDrives, $sDefDrive, $cDrive_Combo) Else __CFF_Fill_Drives($cTreeView, $aAll_Drives, $sDefDrive, $sDefFolder, $aFlags[$g_eCFF_OnlyReturnDeepest], $bNoFolderCheck) EndIf EndIf ; Scroll to show files if required If $sDefFile Then ; Ensure default file visible, highlighted and selected $hItem = _GUICtrlTreeView_GetFirstItem($cTreeView) Do If _GUICtrlTreeView_GetText($cTreeView, $hItem) = $sDefFile Then _GUICtrlTreeView_EnsureVisible($cTreeView, $hItem) _GUICtrlTreeView_ClickItem($cTreeView, $hItem) ExitLoop EndIf $hItem = _GUICtrlTreeView_GetNextChild($cTreeView, $hItem) Until $hItem = 0 Else ; If file scroll selected and files found If $aFlags[$g_eCFF_FileScroll] And $aFill_Ret[2] Then ; Scroll to first file in this branch __CFF_File_Visible($cTreeView, $aFill_Ret) EndIf EndIf ; If defined folder If $sDefFolder Then ; Ensure auto expansion GUICtrlSendToDummy($cRedraw_Dummy) ; Set counter $iRedraw_Count = 0 EndIf ; Parse TV for check data If $bCheckBox Then $aTVCheckData = __CFF_ParseTV($cTreeView) EndIf ; Change to MessageLoop mode Local $nOldOpt = Opt('GUIOnEventMode', 0) While 1 ; Run when any expansion ended or by default If $iRedraw_Count = 5 Then ; Reshow dialog WinSetTrans($hCFF_Win, "", 255) ; Cancel OnTop WinSetOnTop($hCFF_Win, "", 0) ; Reset flag $iRedraw_Count = 0 ; Delete Splash SplashOff() ; Restore user input BlockInput(0) EndIf Switch GUIGetMsg() Case $cCan_Button, $g_cCFF_Esc_Dummy, -3 ; $GUI_EVENT_CLOSE GUIDelete($hCFF_Win) ; Restore previous mode Opt('GUIOnEventMode', $nOldOpt) ; Reset precheck array as required $g_aCFF_PreCheck = $g_aCFF_PreCheckRetain ; And exit Return SetError(5, 0, "") Case $g_cCFF_Refresh_Dummy ; Refresh valid only when drive list to be displayed and refresh allowed If $aFlags[$g_eCFF_AllowRefresh] And ((Not FileExists($sRoot)) Or $bCombo) Then ; Create splash to explain Local $aWin_Pos = WinGetPos($hCFF_Win) SplashOff() ; Close any existing splash screen SplashTextOn("", "Refreshing Tree" & @CRLF & @CRLF & "Please be patient", $aWin_Pos[2], $aWin_Pos[3], $aWin_Pos[0], $aWin_Pos[1], 33) ; Allow redraw $iRedraw_Count = 0 ; Hide dialog until tree drawing complete WinSetTrans($hCFF_Win, "", 1) ; Must be 1 as 0 = hidden ; Force OnTop - near invisible can be hidden WinSetOnTop($hCFF_Win, "", 1) ; If current selections to be retained during refresh If $g_bCFF_RetainSel Then If $bCheckBox Then ; Get current checkbox selections $g_aCFF_Checked_Retain = __CFF_Checked_List($g_hCFF_TreeView) EndIf Else ; Empty selected list If $cList <> 9999 Then GUICtrlSetData($cList, "|") EndIf ; Empty selected variable $sAddFile_List = "" EndIf ; Recreate drive list if no root set If $sRoot = "" Then __CFF_List_Drives($sDrives, $aAll_Drives, $aNetwork_Drives, $iAll_Error, $iNetwork_Error) If $iAll_Error Then Local $aAll_Drives[1] = [0] EndIf If $iNetwork_Error Then Local $aNetwork_Drives[1] = [0] EndIf EndIf ; Check for combo If $bCombo Then ; Empty TreeView _GUICtrlTreeView_DeleteAll($cTreeView) ; Refill combo __CFF_Fill_Combo($iW, $sDrives, $sDefDrive, $cDrive_Combo) ; Reset selected drive $sCurrDrive = "" ; Skip redrawing $iRedraw_Count = 5 Else ; Redraw tree ContinueCase EndIf EndIf Case $cRedraw_Dummy ; Empty TreeView _GUICtrlTreeView_DeleteAll($cTreeView) ; Refill drives __CFF_Fill_Drives($cTreeView, $aAll_Drives, $sDefDrive, $sDefFolder, $aFlags[$g_eCFF_OnlyReturnDeepest], $bNoFolderCheck) ; Increase counter $iRedraw_Count += 1 If $iRedraw_Count < 5 Then ; Re-expand to default folder __CFF_AutoExpand($cTreeView, $iDisplay, $sMask, $aFlags[$g_eCFF_ShowExt], $aFlags[$g_eCFF_HideHS], $aNetwork_Drives, $sDefFolder, $bDefFolder_Open, $iRedraw_Count, $aFlags[$g_eCFF_OnlyReturnDeepest], $bNoFolderCheck, $bCombo, True) ; Native TreeView ; Check expansion correct If _GUICtrlTreeView_GetTree($cTreeView) <> $sDefFolder_Check Then ; Force another redraw GUICtrlSendToDummy($cRedraw_Dummy) Else $iRedraw_Count = 5 EndIf EndIf If $bCheckBox Then ; Reparse TV $aTVCheckData = __CFF_ParseTV($cTreeView) EndIf Case $g_cCFF_DblClk_Dummy If $bCheckBox Then ; Reparse TV $aTVCheckData = __CFF_ParseTV($cTreeView) Else ; Assume selection made - check if valid ContinueCase EndIf Case $cSel_Button, $cAdd_Button ; Get item data $hItem = $g_hCFF_Select_Handle ; Check path is a valid selection $sSelectedPath = __CFF_Check_Selection($g_hCFF_TreeView, $hItem, $sRoot, $iDisplay, $aFlags[$g_eCFF_BothSelectable], $aFlags[$g_eCFF_ShowExt], $sFile_Mask) If $sSelectedPath Then ; Valid item selected If $bSingle_Sel Then GUIDelete($hCFF_Win) ; Restore previous mode Opt('GUIOnEventMode', $nOldOpt) ; Reset precheck array as required $g_aCFF_PreCheck = $g_aCFF_PreCheckRetain ; Return valid path Return $sSelectedPath Else $sAddFile_List = __CFF_List_Add($sAddFile_List, $sSelectedPath, $cList, $aFlags[$g_eCFF_DuplicatesAllowed], $cTreeView) EndIf EndIf Case $cDel_Button ; Check if treeView is active If $g_bCFF_TV_Active Then ; Get TreeView item selected $cItem = GUICtrlRead($cTreeView) $hItem = GUICtrlGetHandle($cItem) ; Check path is a valid selection $sSelectedPath = __CFF_Check_Selection($g_hCFF_TreeView, $hItem, $sRoot, $iDisplay, $aFlags[$g_eCFF_BothSelectable], $aFlags[$g_eCFF_ShowExt], $sFile_Mask) If $sSelectedPath Then ; Valid item selected $sAddFile_List = __CFF_List_Del($sAddFile_List, $sSelectedPath, $cList, $cTreeView) EndIf Else ; Delete list item selected $sAddFile_List = __CFF_List_Del($sAddFile_List, GUICtrlRead($cList), $cList, $cTreeView) ; Set flag $g_bCFF_TV_Active = True EndIf Case $g_cCFF_Select_Dummy If $bCheckBox Then Local $bState, $iItemIndex ; Get handle of selected item $hItem = GUICtrlGetHandle(GUICtrlRead($cTreeView)) ; Determine if item path is a valid selection $sSelectedPath = __CFF_Check_Selection($cTreeView, $hItem, $sRoot, $iDisplay, $aFlags[$g_eCFF_BothSelectable], $aFlags[$g_eCFF_ShowExt], $sFile_Mask) ; If not valid selection If Not $sSelectedPath Then ; If prechecks exist If IsArray($g_aCFF_PreCheck) Then ; Get stored item check state $iItemIndex = _ArraySearch($aTVCheckData, $hItem) ; And force to that state _GUICtrlTreeView_SetChecked($cTreeView, $hItem, $aTVCheckData[$iItemIndex][1]) Else ; If folder checkboxes are shown If Not ($bNoFolderCheck) Then ; Force to unchecked _GUICtrlTreeView_SetChecked($cTreeView, $hItem, False) EndIf EndIf EndIf ; Check if Control or Alt pressed _WinAPI_GetAsyncKeyState(0x11) ; Needed to avoid double setting _WinAPI_GetAsyncKeyState(0x12) If _WinAPI_GetAsyncKeyState(0x11) Or _WinAPI_GetAsyncKeyState(0x12) Then ; Determine checked state $bState = _GUICtrlTreeView_GetChecked($cTreeView, $hItem) ; Find item in array $iItemIndex = _ArraySearch($aTVCheckData, $hItem) ; If checked state has altered If $aTVCheckData[$iItemIndex][1] <> $bState Then ; Store new state $aTVCheckData[$iItemIndex][1] = $bState ; Adjust parents if Alt pressed and only deepest item is to be returned If $aFlags[$g_eCFF_OnlyReturnDeepest] And _WinAPI_GetAsyncKeyState(0x12) Then __CFF_Adjust_Parents($g_hCFF_TreeView, $hItem, $aTVCheckData, $bState) EndIf ; Adjust visible children if Ctrl pressed If _WinAPI_GetAsyncKeyState(0x11) Then __CFF_Adjust_Children($cTreeView, $hItem, $aTVCheckData, $bState) ; Expand item if required If Not _GUICtrlTreeView_GetExpanded($cTreeView, $hItem) Then $g_hCFF_Expand_Handle = $hItem GUICtrlSendToDummy($g_cCFF_Expand_Dummy) EndIf EndIf EndIf EndIf ; Reparse TV $aTVCheckData = __CFF_ParseTV($g_hCFF_TreeView) EndIf Case $cRet_Button, $cRet_Dummy If $bCheckBox Then ; Construct return list Local $sOldSep = Opt("GUIDataSeparatorChar", "\"), $sFullPath $sAddFile_List = "" For $i = 0 To UBound($aTVCheckData) - 1 If $aTVCheckData[$i][1] And $aTVCheckData[$i][2] Then ; Check if valid selection $sFullPath = __CFF_Check_Selection($g_hCFF_TreeView, $aTVCheckData[$i][0], $sRoot, $iDisplay, $aFlags[$g_eCFF_BothSelectable], $aFlags[$g_eCFF_ShowExt], $sFile_Mask) If $sFullPath Then $sAddFile_List &= $sFullPath & "|" EndIf Next Opt("GUIDataSeparatorChar", $sOldSep) ; Check if only deepest items are to be returned If $aFlags[$g_eCFF_OnlyReturnDeepest] Then ; Convert list to array Local $aDeepest = StringSplit($sAddFile_List, "|") ; Loop through array checking if item forms part of preceding item For $i = $aDeepest[0] - 2 To 1 Step -1 $sFullPath = $aDeepest[$i] If StringInStr(FileGetAttrib($sFullPath), "D") Then If StringInStr($aDeepest[$i + 1], $aDeepest[$i]) Then ; Remove item from list $sAddFile_List = StringReplace($sAddFile_List, $aDeepest[$i] & "|", "") EndIf EndIf Next ; If there were prechecked items If IsArray($g_aCFF_PreCheck) Then ; Loop through to remove any parent items that were not fully expanded For $i = 1 To $aDeepest[0] For $j = 0 To UBound($g_aCFF_PreCheck) - 1 If StringInStr($g_aCFF_PreCheck[$j], $aDeepest[$i]) Then $sAddFile_List = StringReplace($sAddFile_List, $aDeepest[$i] & "|", "") EndIf Next Next EndIf EndIf ; Now add unused prechecked items For $i = 0 To UBound($g_aCFF_PreCheck) - 1 If $g_aCFF_PreCheck[$i] Then $sAddFile_List &= $g_aCFF_PreCheck[$i] & "|" EndIf Next EndIf ; Close dialog GUIDelete($hCFF_Win) ; Restore previous mode Opt('GUIOnEventMode', $nOldOpt) ; Reset precheck array as required $g_aCFF_PreCheck = $g_aCFF_PreCheckRetain ; Remove final | from return string and return Return StringTrimRight($sAddFile_List, 1) Case $g_cCFF_Expand_Dummy ; Get expanded item handle and ControlID $hItem = $g_hCFF_Expand_Handle $cItem = $g_cCFF_Expand_CID ; Get path of item to expand $sSelectedPath = $sRoot & StringReplace(_GUICtrlTreeView_GetTree($cTreeView, $hItem), "|", "\") ; Check if dummy child exists or has already been filled Local $hFirstChild = _GUICtrlTreeView_GetFirstChild($g_hCFF_TreeView, $hItem) Local $sFirstChild = _GUICtrlTreeView_GetText($g_hCFF_TreeView, $hFirstChild) ; If dummy child exists If $sFirstChild = "" Then ; Delete the dummy _GUICtrlTreeView_Delete($g_hCFF_TreeView, $hFirstChild) ; Fill with content $aFill_Ret = __CFF_Fill_Branch($cTreeView, $cItem, $sSelectedPath, $iDisplay, $sMask, $aFlags[$g_eCFF_ShowExt], $aFlags[$g_eCFF_HideHS], $aNetwork_Drives, $aFlags[$g_eCFF_OnlyReturnDeepest], $bNoFolderCheck) EndIf ; If file scroll selected AND files were found AND the branch is being expanded If $aFlags[$g_eCFF_FileScroll] And $aFill_Ret[2] And _GUICtrlTreeView_GetExpanded($g_hCFF_TreeView, $hItem) Then ; Scroll to first file in this branch __CFF_File_Visible($g_hCFF_TreeView, $aFill_Ret) EndIf If $bCheckBox Then ; Reparse TV $aTVCheckData = __CFF_ParseTV($g_hCFF_TreeView) EndIf Case $cDrive_Combo If GUICtrlRead($cDrive_Combo) <> $sCurrDrive Then ; Get drive chosen $sCurrDrive = GUICtrlRead($cDrive_Combo) If $sRoot Then ; Delete current content _GUICtrlTreeView_DeleteAll($g_hCFF_TreeView) Else ; Show TV GUICtrlSetState($cTreeView, 16) ; $GUI_SHOW EndIf ; Set root path $sRoot = $sCurrDrive & "\" ; Fill TV $aFill_Ret = __CFF_Fill_Branch($cTreeView, $cTreeView, $sRoot, $iDisplay, $sMask, $aFlags[$g_eCFF_ShowExt], $aFlags[$g_eCFF_HideHS], $aNetwork_Drives, $aFlags[$g_eCFF_OnlyReturnDeepest], $bNoFolderCheck) ; If file scroll selected and files found If $aFlags[$g_eCFF_FileScroll] And $aFill_Ret[2] Then ; Scroll to first file in this branch __CFF_File_Visible($cTreeView, $aFill_Ret) EndIf EndIf EndSwitch WEnd EndFunc ;==>_CFF_Choose ; #FUNCTION# ========================================================================================================= ; Name...........: _CFF_Embed ; Description ...: Creates the folder tree within an existing treeview and optional list ; Syntax.........: _CFF_Embed ($cTreeView, [$sRoot = ""[, $sMask = "*"[, $iDisplay = 0[, $cReturn = 0[, $cList = 0]]]]) ; Parameters ....: $cTreeView - Handle/ControlID of TreeView to use - only required parameter! ; $sRoot - Path tree to display ; If a filename is passed, the tree for the folder opens with the file highlighted ; To permit drive selection: ; "" (default) = All ready drives shown ; List of drive letters (e.g. "cde") = Limit display to these drives if ready ; Add "|drive letter" (e.g. "cde|d" or "|d") = Highlight and expand specified drive tree on opening ; or "|folder path" (e.g. "cde|d:\folder) = Highlight specified folder (add "\" to expand folder) ; $sMask - Filter for result. Multiple filters must be separated by ";" ; Use "|" to separate 3 possible sets of filters: "Include|Exclude|Exclude_Folders" ; Include = Files/Folders to include (default = "*" [all]) ; Exclude = Files/Folders to exclude (default = "" [none]) ; Exclude_Folders = only used if the basic $iDisplay = 0 to exclude defined folders (default = "" [none]) ; $iDisplay - Determine what is displayed in the tree ; 0 - Entire folder tree and all matching files within folders - only files can be selected (default) ; - Double clicking folders will expand/contract contents, NOT select (see option 16 below) ; 1 - All matching files within the specified folder - subfolders are not displayed ; - Doubleclick will select file ; 2 - Entire folder tree only - no files ; - Doubleclick will select folder ; - All modes: "Enter" button will always select ; + 4 - Do not display Hidden files/folders ; + 8 - Do not display System files/folders ; + 16 - Both files and folders can be selected - only valid if $iDisplay set to 0 ; + 32 - Allow duplicate selections when clicking ; + 64 - Hide file extensions (only valid if file mask specifies a single extension) ; + 128 - Scroll to first file in folder - only valid if basic $iDisplay set to 0 ; + 512 - When using checkboxes only return deepest items on path - default return all checked items ; + 1024 - Allow drive list refresh ; $cReturn - Set single/multiple selection ; 0 - Single selection (default). Doubleclick returns item - @extended set to 0 ; 1 - Multiple selection. Doubleclick adds item to return string ; Valid ControlID - Control to action to end multiple selection - @extended set to 0 ; $cList - [Optional] ControlID of list to fill with multiple selections ; Requirement(s).: v3.3 + ; Return values .: Success: Single selection = String containing selected item ; Multi selection = String of selected items delimited by "|" ; Failure: Returns "" and sets @error as follows: ; 1 = Invalid TreeView ControlID ; 2 = Invalid $sPath parameter ; 3 = Invalid $iDisplay parameter ; 4 = Invalid $cList ControlID ; 5 = Invalid or missing $cReturn ControlID ; 6 = Empty tree ; 7 = Esc pressed to exit ; Author ........: Melba23 ; Modified ......: ; Remarks .......: - Press "ESC" to cancel selection process ; - For multiple selection: ; If list: ; Doubleclick treeview item to add to list ; Press Ctrl while doubleclicking to delete last instance of item ; If checkboxes: ; Use checkboxes to select items ; Pressing Ctrl when (un)checking sets all children to same state ; Pressing Alt when (un)checking sets parents to same state if no other checked boxes on path ; Use "{ENTER}" key or passed control to return selection - @extended set to 1 ; - If drive refresh allowed, use _CFF_Refresh function via HotKey to refresh drive list ; Example........: Yes ;===================================================================================================================== Func _CFF_Embed($cTreeView, $sRoot = "", $sMask = "*", $iDisplay = 0, $cReturn = 0, $cList = 0) Local $bSingle_Sel, $cItem, $hItem, $sSelectedPath, $sAddFile_List = "" Local $sDrives = "", $sDefDrive = "", $sDefFolder, $sDefFolder_Check, $sDefFile, $aFill_Ret[3], $aAll_Drives, $aNetwork_Drives Local $iRedraw_Count, $bDefFolder_Open = False, $bCheckBox = False, $aTVCheckData, $aOldCheckData, $bNoFolderCheck = False Local $aFlags[$g_eCFF_FlagMax] = [True, 0, False, False, False, False, False, False] ; Set default values $g_bCFF_AutoExpand = False ; Check treeview type and set TV_ID Local $bNative_TV = True, $vTV_ID = $cTreeView If IsHWnd($cTreeView) Then $g_hCFF_TreeView = $cTreeView $bNative_TV = False $vTV_ID = $g_hCFF_TreeView Else If Not IsHWnd(GUICtrlGetHandle($cTreeView)) Then ; Reset precheck array as required $g_aCFF_PreCheck = $g_aCFF_PreCheckRetain Return SetError(1, 0, "") Else $g_hCFF_TreeView = GUICtrlGetHandle($cTreeView) EndIf EndIf ; Check path Switch $sRoot Case "", Default $sRoot = "" Case Else ; If a path If FileExists($sRoot) Then ; Check if file or folder If StringInStr(FileGetAttrib($sRoot), "D") Then ; Add trailing \ if needed If StringRight($sRoot, 1) <> "\" Then $sRoot &= "\" EndIf Else $sDefFile = StringRegExpReplace($sRoot, "^.*\\", "") $sRoot = StringRegExpReplace($sRoot, "(^.*\\)(.*)", "\1") EndIf Else ; Split to look for eventual drive|default info - ignore combo section Local $aSplit = StringSplit($sRoot, "|") If Not @error And $aSplit[0] < 4 Then ; Check required drive list If Not StringRegExp($aSplit[1], "(?i)^[a-z]*$") Then ; Reset precheck array as required $g_aCFF_PreCheck = $g_aCFF_PreCheckRetain Return SetError(1, 2, "") EndIf ; And store $sDrives = StringUpper($aSplit[1]) ; Check for default drive If $aSplit[0] > 1 Then $sDefDrive = StringUpper(StringLeft($aSplit[2], 1)) ; Check if default in drive list If $sDrives And (Not StringInStr($sDrives, $sDefDrive)) Then ; Clear if not $sDefDrive = "" Else ; Add colon If $sDefDrive Then $sDefDrive &= ":" EndIf EndIf ; Is it a valid folder path? If FileExists($aSplit[2]) And StringInStr(FileGetAttrib($aSplit[2]), "D") Then $sDefFolder = $aSplit[2] ; Check if trailing backslash If StringRight($sDefFolder, 1) = "\" Then ; Set flag $bDefFolder_Open = True ; Remove the trailing backslash $sDefFolder = StringTrimRight($sDefFolder, 1) EndIf ; Replace backslashes for comparison when expanded $sDefFolder_Check = StringReplace($sDefFolder, "\", "|") EndIf EndIf ; Clear root parameter to show drive choice required $sRoot = "" Else ; Reset precheck array as required $g_aCFF_PreCheck = $g_aCFF_PreCheckRetain ; Not valid path or drive list Return SetError(1, 1, "") EndIf EndIf EndSwitch ; Create drive lists if no root set Local $iAll_Error = 0, $iNetwork_Error = 0 If $sRoot = "" Then __CFF_List_Drives($sDrives, $aAll_Drives, $aNetwork_Drives, $iAll_Error, $iNetwork_Error) If $iAll_Error Then Local $aAll_Drives[1] = [0] EndIf If $iNetwork_Error Then Local $aNetwork_Drives[1] = [0] EndIf EndIf ; Check Mask If $sMask = Default Then $sMask = "*" EndIf ; Extract File mask (needed for hide extension code) Local $aMaskSplit = StringSplit($sMask, "|") Local $sFile_Mask = $aMaskSplit[1] ; Check Display parameter $iDisplay = __CFF_Check_Display($iDisplay, $sFile_Mask, $aFlags) If @error Then ; Reset precheck array as required $g_aCFF_PreCheck = $g_aCFF_PreCheckRetain Return SetError(3, 0, "") EndIf ; Verify precheck list if set If IsArray($g_aCFF_PreCheck) Then __CFF_Verify_PreCheck($g_aCFF_PreCheck, $iDisplay, $aFlags[$g_eCFF_BothSelectable]) EndIf ; Check for return type and possible return ControlID Switch $cReturn Case 0 ; Single select $bSingle_Sel = True ; Prevent from firing $cReturn = 9999 Case Else ; Multi select $bSingle_Sel = False ; Check if valid ControlID If Not IsHWnd(GUICtrlGetHandle($cReturn)) Then ; Prevent from firing $cReturn = 9999 EndIf EndSwitch ; If list passed check if valid ControlID If $cList And Not IsHWnd(GUICtrlGetHandle($cList)) Then ; Reset precheck array as required $g_aCFF_PreCheck = $g_aCFF_PreCheckRetain Return SetError(5, 0, "") EndIf ; Check if TreeView is using checkboxes If BitAND(_WinAPI_GetWindowLong($g_hCFF_TreeView, 0xFFFFFFF0), 0x0100) Then ; $GWL_STYLE, $TVS_CHECKBOXES $bCheckBox = True ; Check if folder checkboxes should be hidden - only files selectable and no prechecks If $iDisplay = 0 And Not ($aFlags[$g_eCFF_BothSelectable]) And Not (IsArray($g_aCFF_PreCheck)) Then $bNoFolderCheck = True EndIf EndIf ; Create dummy controls $g_cCFF_Expand_Dummy = GUICtrlCreateDummy() ; Fires when [+] clicked $g_cCFF_Select_Dummy = GUICtrlCreateDummy() ; Fires when item checked $g_cCFF_Click_Dummy = GUICtrlCreateDummy() ; Fires on Click $g_cCFF_DblClk_Dummy = GUICtrlCreateDummy() ; Fires on DblClk $g_cCFF_Esc_Dummy = GUICtrlCreateDummy() ; Fires on ESC $g_cCFF_Refresh_Dummy = GUICtrlCreateDummy() ; Fires on refresh Local $cRet_Dummy = GUICtrlCreateDummy() ; Fires on ENTER Local $cRedraw_Dummy = GUICtrlCreateDummy() ; Fires on Redraw key ; Set accel keys Local $aAccelKeys[2][2] = [["{ENTER}", $cRet_Dummy], ["{ESC}", $g_cCFF_Esc_Dummy]] GUISetAccelerators($aAccelKeys) ; Fill tree If $sRoot Then ; If root folder specified then fill TV $aFill_Ret = __CFF_Fill_Branch($vTV_ID, $cTreeView, $sRoot, $iDisplay, $sMask, $aFlags[$g_eCFF_ShowExt], $aFlags[$g_eCFF_HideHS], $aNetwork_Drives, $aFlags[$g_eCFF_OnlyReturnDeepest], $bNoFolderCheck) Else __CFF_Fill_Drives($vTV_ID, $aAll_Drives, $sDefDrive, $sDefFolder, $aFlags[$g_eCFF_OnlyReturnDeepest], $bNoFolderCheck) EndIf ; Ensure first file visible if selecting files only and displaying both files and folders If (Not $aFlags[$g_eCFF_BothSelectable]) And $aFill_Ret[2] Then ; Last file visible _GUICtrlTreeView_EnsureVisible($g_hCFF_TreeView, $aFill_Ret[2]) ; Last folder visible _GUICtrlTreeView_EnsureVisible($g_hCFF_TreeView, $aFill_Ret[1]) EndIf ; Highlight passed file if required If $sDefFile Then $hItem = _GUICtrlTreeView_GetFirstItem($g_hCFF_TreeView) Do If _GUICtrlTreeView_GetText($g_hCFF_TreeView, $hItem) = $sDefFile Then _GUICtrlTreeView_EnsureVisible($g_hCFF_TreeView, $hItem) _GUICtrlTreeView_ClickItem($g_hCFF_TreeView, $hItem) ExitLoop EndIf $hItem = _GUICtrlTreeView_GetNextChild($g_hCFF_TreeView, $hItem) Until $hItem = 0 EndIf ; If defined folder If $sDefFolder Then ; Fire auto expansion in loop GUICtrlSendToDummy($cRedraw_Dummy) ; Set counter $iRedraw_Count = 0 EndIf If $bCheckBox Then ; Parse TV for check data $aTVCheckData = __CFF_ParseTV($g_hCFF_TreeView) $aOldCheckData = $aTVCheckData EndIf ; Change to MessageLoop mode Local $nOldOpt = Opt('GUIOnEventMode', 0) ; Clear flag for Ret key pressed Local $iRet_Pressed = 0 While 1 ; Clear splash after refresh If $iRedraw_Count >= 5 Then SplashOff() $iRedraw_Count = 0 EndIf Switch GUIGetMsg() Case $g_cCFF_Refresh_Dummy If $aFlags[$g_eCFF_AllowRefresh] And (Not FileExists($sRoot)) Then ; Create splash to explain Local $aWin_Pos = WinGetPos($g_hCFF_TreeView) SplashOff() ; Close any existing splash screen SplashTextOn("", "Refreshing Tree" & @CRLF & @CRLF & "Please be patient", $aWin_Pos[2], $aWin_Pos[3], $aWin_Pos[0], $aWin_Pos[1], 33) $iRedraw_Count = 0 ; If current selections to be retained during refresh If $g_bCFF_RetainSel Then If $bCheckBox Then ; Get current checkbox selections $g_aCFF_Checked_Retain = __CFF_Checked_List($g_hCFF_TreeView) EndIf Else ; Empty selected list If $cList <> 9999 Then GUICtrlSetData($cList, "|") EndIf ; Empty selected variable $sAddFile_List = "" EndIf ; Recreate drive list if no root set If $sRoot = "" Then __CFF_List_Drives($sDrives, $aAll_Drives, $aNetwork_Drives, $iAll_Error, $iNetwork_Error) If $iAll_Error Then Local $aAll_Drives[1] = [0] EndIf If $iNetwork_Error Then Local $aNetwork_Drives[1] = [0] EndIf EndIf GUICtrlSetData($g_cCFF_Refresh_Dummy, 9999) ; And redraw the TreeView ContinueCase EndIf Case $cRedraw_Dummy ; Empty TreeView _GUICtrlTreeView_DeleteAll($g_hCFF_TreeView) ; Refill drives __CFF_Fill_Drives($g_hCFF_TreeView, $aAll_Drives, $sDefDrive, $sDefFolder, $aFlags[$g_eCFF_OnlyReturnDeepest], $bNoFolderCheck) ; Increase counter $iRedraw_Count += 1 If $iRedraw_Count < 5 Then ; Re-expand to default folder __CFF_AutoExpand($g_hCFF_TreeView, $iDisplay, $sMask, $aFlags[$g_eCFF_ShowExt], $aFlags[$g_eCFF_HideHS], $aNetwork_Drives, $sDefFolder, $bDefFolder_Open, $iRedraw_Count, $aFlags[$g_eCFF_OnlyReturnDeepest], $bNoFolderCheck) ; Check expansion correct If _GUICtrlTreeView_GetTree($g_hCFF_TreeView) <> $sDefFolder_Check Then ; Force another redraw GUICtrlSendToDummy($cRedraw_Dummy) Else $iRedraw_Count = 5 EndIf EndIf ; Reparse TV If $bCheckBox Then $aTVCheckData = __CFF_ParseTV($g_hCFF_TreeView) EndIf Case $g_cCFF_Click_Dummy If $bCheckBox Then ; Loop through current TreeView items to see if a checkbox has changed state ; Get handle of selected item If $bNative_TV Then $hItem = GUICtrlGetHandle(GUICtrlRead($cTreeView)) Else $hItem = _GUICtrlTreeView_GetSelection($g_hCFF_TreeView) EndIf For $i = 0 To UBound($aOldCheckData) - 1 ; Compare handle to existing item If $hItem <> $aOldCheckData[$i][0] Then ExitLoop ; TreeView was obviously expanded ; Compare item checkbox states If _GUICtrlTreeView_GetChecked($g_hCFF_TreeView, $hItem) <> $aOldCheckData[$i][1] Then ; Determine if item path is a valid selection $sSelectedPath = __CFF_Check_Selection($g_hCFF_TreeView, $hItem, $sRoot, $iDisplay, $aFlags[$g_eCFF_BothSelectable], $aFlags[$g_eCFF_ShowExt], $sFile_Mask) ; If not valid selection If Not $sSelectedPath Then ; If prechecks exist If IsArray($g_aCFF_PreCheck) Then ; Force to that state _GUICtrlTreeView_SetChecked($cTreeView, $hItem, $aOldCheckData[$i][1]) Else ; If folder checkboxes are shown If Not ($bNoFolderCheck) Then ; Force to unchecked _GUICtrlTreeView_SetChecked($cTreeView, $hItem, False) EndIf EndIf EndIf ; No point in looking further so check for parent/child adjustments $g_hCFF_Select_Handle = $hItem GUICtrlSendToDummy($g_cCFF_Select_Dummy) ExitLoop EndIf ; Get next item handle $hItem = _GUICtrlTreeView_GetNext($g_hCFF_TreeView, $hItem) ; Exit if TreeView had been contracted If $hItem = 0 Then ExitLoop Next EndIf Case $g_cCFF_Select_Dummy If $bCheckBox Then ; Check if Control or Alt pressed _WinAPI_GetAsyncKeyState(0x11) ; Needed to avoid double setting _WinAPI_GetAsyncKeyState(0x12) If _WinAPI_GetAsyncKeyState(0x11) Or _WinAPI_GetAsyncKeyState(0x12) Then ; Get handle of selected item $hItem = $g_hCFF_Select_Handle ; Determine checked state Local $bState = _GUICtrlTreeView_GetChecked($cTreeView, $hItem) ; Find item in array Local $iItemIndex = _ArraySearch($aOldCheckData, $hItem) ; If checked state has altered If $aOldCheckData[$iItemIndex][1] <> $bState Then ; Store new state $aOldCheckData[$iItemIndex][1] = $bState ; Adjust parents if only deepest item is to be returned and Alt pressed If $aFlags[$g_eCFF_OnlyReturnDeepest] And _WinAPI_GetAsyncKeyState(0x12) Then __CFF_Adjust_Parents($g_hCFF_TreeView, $hItem, $aOldCheckData, $bState) EndIf ; Adjust visible children if Ctrl pressed If _WinAPI_GetAsyncKeyState(0x11) Then __CFF_Adjust_Children($cTreeView, $hItem, $aOldCheckData, $bState) ; Expand item if required If Not _GUICtrlTreeView_GetExpanded($cTreeView, $hItem) Then $g_hCFF_Expand_Handle = $hItem GUICtrlSendToDummy($g_cCFF_Expand_Dummy) EndIf EndIf EndIf EndIf ; Reparse TV $aTVCheckData = __CFF_ParseTV($g_hCFF_TreeView) $aOldCheckData = $aTVCheckData EndIf Case $cRet_Dummy ; Set flag $iRet_Pressed = 1 If $bSingle_Sel Then ; Get selected item If $bNative_TV Then $hItem = GUICtrlGetHandle(GUICtrlRead($cTreeView)) Else $hItem = _GUICtrlTreeView_GetSelection($g_hCFF_TreeView) EndIf If $hItem Then ; Determine item path $sAddFile_List = $sRoot & StringReplace(_GUICtrlTreeView_GetTree($g_hCFF_TreeView, $hItem), "|", "\") Switch $iDisplay Case 2 ; Folders only Case Else ; Files only StringReplace(FileGetAttrib($sAddFile_List), "D", "") ; Is it a folder? If @extended Then $sAddFile_List = "" EndIf ; Hide extension? If $aFlags[$g_eCFF_ShowExt] = False Then $sAddFile_List &= StringTrimLeft($sFile_Mask, 1) EndIf EndSwitch EndIf EndIf ContinueCase Case $cReturn If $bCheckBox Then ; Reparse TV $aTVCheckData = __CFF_ParseTV($g_hCFF_TreeView) $aOldCheckData = $aTVCheckData ; Construct return list Local $sOldSep = Opt("GUIDataSeparatorChar", "\"), $sFullPath $sAddFile_List = "" For $i = 0 To UBound($aTVCheckData) - 1 If $aTVCheckData[$i][1] And $aTVCheckData[$i][2] Then ; Check if valid selection $sFullPath = __CFF_Check_Selection($g_hCFF_TreeView, $aTVCheckData[$i][0], $sRoot, $iDisplay, $aFlags[$g_eCFF_BothSelectable], $aFlags[$g_eCFF_ShowExt], $sFile_Mask) If $sFullPath Then $sAddFile_List &= $sFullPath & "|" EndIf Next Opt("GUIDataSeparatorChar", $sOldSep) ; Check if only deepest items are to be returned If $aFlags[$g_eCFF_OnlyReturnDeepest] Then ; Convert list to array Local $aDeepest = StringSplit($sAddFile_List, "|") ; Loop through array checking if item forms part of preceding item For $i = $aDeepest[0] - 2 To 1 Step -1 $sFullPath = $aDeepest[$i] If StringInStr(FileGetAttrib($sFullPath), "D") Then If StringInStr($aDeepest[$i + 1], $aDeepest[$i]) Then ; Remove item from list $sAddFile_List = StringReplace($sAddFile_List, $aDeepest[$i] & "|", "") EndIf EndIf Next ; If there were prechecked items If IsArray($g_aCFF_PreCheck) Then ; Loop through to remove any parent items that were not fully expanded For $i = 1 To $aDeepest[0] For $j = 0 To UBound($g_aCFF_PreCheck) - 1 If StringInStr($g_aCFF_PreCheck[$j], $aDeepest[$i]) Then $sAddFile_List = StringReplace($sAddFile_List, $aDeepest[$i] & "|", "") EndIf Next Next EndIf EndIf ; Now add unused prechecked items For $i = 0 To UBound($g_aCFF_PreCheck) - 1 If $g_aCFF_PreCheck[$i] Then $sAddFile_List &= $g_aCFF_PreCheck[$i] & "|" EndIf Next EndIf ; Clear treeview and list _GUICtrlTreeView_DeleteAll($g_hCFF_TreeView) GUICtrlSetData($cList, "|") ; Restore previous mode Opt('GUIOnEventMode', $nOldOpt) ; Cancel Accel keys GUISetAccelerators(0) ; Reset precheck array as required $g_aCFF_PreCheck = $g_aCFF_PreCheckRetain ; Return list of files selected Return SetError(0, $iRet_Pressed, StringTrimRight($sAddFile_List, 1)) Case $g_cCFF_DblClk_Dummy If $bCheckBox Then ; Reparse TV $aTVCheckData = __CFF_ParseTV($g_hCFF_TreeView) Else ; Get item data If $bNative_TV Then $hItem = GUICtrlGetHandle(GUICtrlRead($cTreeView)) Else $hItem = _GUICtrlTreeView_GetSelection($g_hCFF_TreeView) EndIf ; Check path is a valid selection $sSelectedPath = __CFF_Check_Selection($g_hCFF_TreeView, $hItem, $sRoot, $iDisplay, $aFlags[$g_eCFF_BothSelectable], $aFlags[$g_eCFF_ShowExt], $sFile_Mask) If $sSelectedPath Then ; Valid item selected If $bSingle_Sel Then ; Clear treeview _GUICtrlTreeView_DeleteAll($g_hCFF_TreeView) ; Restore previous mode Opt('GUIOnEventMode', $nOldOpt) ; Cancel Accel keys GUISetAccelerators(0) ; Reset precheck array as required $g_aCFF_PreCheck = $g_aCFF_PreCheckRetain ; Return valid path Return $sSelectedPath Else ; Check if Ctrl pressed _WinAPI_GetAsyncKeyState(0x11) ; Needed to avoid double setting If _WinAPI_GetAsyncKeyState(0x11) Then $sAddFile_List = __CFF_List_Del($sAddFile_List, $sSelectedPath, $cList, $g_hCFF_TreeView) Else $sAddFile_List = __CFF_List_Add($sAddFile_List, $sSelectedPath, $cList, $aFlags[$g_eCFF_DuplicatesAllowed], $g_hCFF_TreeView) EndIf EndIf EndIf EndIf Case $g_cCFF_Expand_Dummy ; Get expanded item hamdle and ControlID $hItem = $g_hCFF_Expand_Handle $cItem = $g_cCFF_Expand_CID ; Force use of handle for non-native control If Not $bNative_TV Then $cItem = $hItem $sSelectedPath = $sRoot & StringReplace(_GUICtrlTreeView_GetTree($g_hCFF_TreeView, $hItem), "|", "\") ; Check if dummy child exists or has already been filled Local $hFirstChild = _GUICtrlTreeView_GetFirstChild($g_hCFF_TreeView, $hItem) Local $sFirstChild = _GUICtrlTreeView_GetText($g_hCFF_TreeView, $hFirstChild) ; If dummy child exists If $sFirstChild = "" Then ; Fill with content $aFill_Ret = __CFF_Fill_Branch($vTV_ID, $cItem, $sSelectedPath, $iDisplay, $sMask, $aFlags[$g_eCFF_ShowExt], $aFlags[$g_eCFF_HideHS], $aNetwork_Drives, $aFlags[$g_eCFF_OnlyReturnDeepest], $bNoFolderCheck) ; Delete the dummy _GUICtrlTreeView_Delete($g_hCFF_TreeView, $hFirstChild) EndIf ; If file scroll selected AND files were found AND the branch is being expanded If $aFlags[$g_eCFF_FileScroll] And $aFill_Ret[2] And _GUICtrlTreeView_GetExpanded($g_hCFF_TreeView, $hItem) Then ; Scroll to first file in this branch __CFF_File_Visible($g_hCFF_TreeView, $aFill_Ret) EndIf If $bCheckBox Then ; Reparse TV $aTVCheckData = __CFF_ParseTV($g_hCFF_TreeView) ; Save current state $aOldCheckData = $aTVCheckData EndIf Case $g_cCFF_Esc_Dummy ; Clear treeview and list _GUICtrlTreeView_DeleteAll($g_hCFF_TreeView) GUICtrlSetData($cList, "|") ; Restore previous mode Opt('GUIOnEventMode', $nOldOpt) ; Cancel Accel keys GUISetAccelerators(0) ; Reset precheck array as required $g_aCFF_PreCheck = $g_aCFF_PreCheckRetain ; Return Return SetError(7, 0, "") EndSwitch WEnd EndFunc ;==>_CFF_Embed ; #FUNCTION# ========================================================================================================= ; Name...........: _CFF_Refresh ; Description ...: Re-reads drives to refresh TreeView - also toggles delete/retain of existing selections ; Syntax.........: _CFF_Refresh($vRetain) ; Parameters ....: $vRetain - 0 = Do not retain existing selected values when refreshing ; 1 = Retain existing selected values when refreshing ; Requirement(s).: v3.3.14.5 ; Return values .: State of delete/retain flag ; Author ........: Melba23 ; Modified ......: ; Remarks .......: - When called by pressing the "Cancel" split button (_Choose) or via a HotKey (_Embed) ; re-reads the available drives if no path is defined and refreshes the TreeView ; - When called directly with $vRetain = 0/1 sets flag to determine if existing selections are deleted or retained ; Example........: Yes ;===================================================================================================================== Func _CFF_Refresh($vRetain = 9999) #forceref $vRetain ; Check if parameter exists Eval("vRetain") If @error Then ; No param when fired via HotKey so fire refresh dummy GUICtrlSendToDummy($g_cCFF_Refresh_Dummy, 9999) Else ; Param exists so fired programatically to set/clear delete/retain flag Switch Eval("vRetain") Case 9999 ; Do nothing Case 0 $g_bCFF_RetainSel = False ; Clear selected checkbox array $g_aCFF_Checked_Retain = 0 Case 1 $g_bCFF_RetainSel = True EndSwitch EndIf Return $g_bCFF_RetainSel EndFunc ;==>_CFF_Refresh ; #FUNCTION# ========================================================================================================= ; Name...........: _CFF_SetPreCheck ; Description ...: Sets a list of files/folders which will be checked when expanded ; Syntax.........: _CFF_SetPreCheck ($aPreCheck_List [, $bNoPartial = True])) ; Parameters ....: $aPreCheck_List - Array holding paths of files/folders to check on expansion (or non-array to clear) ; $bNoPartial - True (default) = partial paths removed from list ; False = List untouched ; $bVolatile - True (default) = List cleared after call to _CFF_Choose/Embed ; False = List remains active for future calls ; Requirement(s).: v3.3 + ; Return values .: 1 = Precheck list set ; 0 = Precheck list cleared ; @extended = state of $g-bCFF_PreCheckVolatile flag ; Author ........: Melba23 ; Modified ......: ; Remarks .......: - Items will be checked when branch containing the item is expanded. If the item has not been expanded ; it will be automatically included in the return list. ; - The UDF will remove any invalid paths and any that would not be displayed in the tree because of the ; display setting ; - Folder paths can be with/without a trailing \ which is automatically added ; - Passing a non-array parameter clears pre-check list ; - Partial paths are part of other paths within the array. If the "+ 512" (only deepest element returned) ; option is used these paths need to be removed from the array ; Example........: Yes ;===================================================================================================================== Func _CFF_SetPreCheck($aPreCheck_List, $bNoPartial = True, $bVolatile = True) If Not IsArray($aPreCheck_List) Then ; Clear list $aPreCheck_List = "" Else Local $sTest, $sTestSRE, $bFolder, $iMax = UBound($aPreCheck_List) - 1 If $bNoPartial = Default Then $bNoPartial = True If $bVolatile = Default Then $bVolatile = True ; Loop through elements For $i = 0 To $iMax ; Extract path $sTest = $aPreCheck_List[$i] ; Check for drives If StringRegExp($sTest, "^[A-Za-z]:\\?$") Then ; Check if valid (add trailing "\" if required) and delete if not If DriveStatus($sTest & ((StringRight($sTest, 1) = "\") ? ("") : ("\"))) <> "READY" Then $aPreCheck_List[$i] = "" ; No point in checking further ContinueLoop EndIf EndIf ; Check for partial paths if NoPartial set If $bNoPartial Then ; Check if folder If StringInStr(FileGetAttrib($sTest), "D") Then ; Force a trailing "\" If StringRight($sTest, 1) <> "\" Then $sTest &= "\" $aPreCheck_List[$i] &= "\" EndIf ; Set flag $bFolder = True ; Escape any SRE special characters $sTestSRE = StringRegExpReplace($sTest, "[][$^.{}()+\\-]", "\\$0") Else ; Clear flag $bFolder = False EndIf ; Compare to all other elements For $j = 0 To $iMax ; If not test element itself AND is folder - check for partial path If $j <> $i And $bFolder And StringRegExp($aPreCheck_List[$j], "^" & $sTestSRE) Then ; And delete if so $aPreCheck_List[$i] = "" ; No point in checking further ExitLoop EndIf Next EndIf Next EndIf ; Store final array $g_aCFF_PreCheck = $aPreCheck_List ; Check for precheck volatility If $bVolatile Then $g_aCFF_PreCheckRetain = "" Else $g_aCFF_PreCheckRetain = $aPreCheck_List EndIf ; Return action code Return SetExtended(IsArray($g_aCFF_PreCheckRetain), IsArray($g_aCFF_PreCheck)) EndFunc ;==>_CFF_SetPreCheck ; #FUNCTION# ========================================================================================================= ; Name...........: _CFF_RegMsg ; Description ...: Registers WM_NOTIFY for TreeView doubleclick and item expansion and WM_COMMAND for list focus ; Syntax.........: _CFF_RegMsg([$bNOTIFY = True[, $bCOMMAND = True]]) ; Parameters.....: $bNOTIFY - True (default) = Register WM_NOTIFY handler function ; $bCOMMAND - True (default) = Register WM_COMMAND handler function ; Requirement(s).: v3.3 + ; Return values .: 0 - No handlers registered ; 1 - WM_NOTIFY handler registered ; 2 - WM_COMMAND handler registered ; 3 - Both handlers registerd ; Author ........: Melba23 ; Modified ......: ; Remarks .......: If a script has existing WM_NOTIFY or WM_COMMAND handlers then do not register the relevant handler ; using this function but call it directly from within the existing message handler ; Example........: Yes ;===================================================================================================================== Func _CFF_RegMsg($bNOTIFY = True, $bCommand = True) ; Register required messages Local $iRet = 0 If $bNOTIFY Then $iRet = GUIRegisterMsg(0x004E, "_CFF_WM_NOTIFY_Handler") ; $WM_NOTIFY EndIf If $bCommand Then $iRet = 2 * GUIRegisterMsg(0x0111, "_CFF_WM_COMMAND_Handler") ; $WM_COMMAND EndIf Return $iRet EndFunc ;==>_CFF_RegMsg ; #FUNCTION# ========================================================================================================= ; Name...........: _CFF_WM_NOTIFY_Handler ; Description ...: Windows message handler for WM_NOTIFY - reacts to doubleclick and item expansion on TreeView ; Syntax.........: _CFF_WM_NOTIFY_Handler($hWnd, $iMsg, $wParam, $lParam) ; Requirement(s).: v3.3 + ; Return values..: None ; Author ........: Melba23 - thanks to guinness for help with the #*@#*%# Struct !!!! ; Modified ......: ; Remarks .......: If a WM_NOTIFY handler already registered, then call this function from within that handler ; Example........: Yes ;===================================================================================================================== Func _CFF_WM_NOTIFY_Handler($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam ; Create NMTREEVIEW structure Local $tStruct = DllStructCreate("struct;hwnd hWndFrom;uint_ptr IDFrom;INT Code;endstruct;" & _ "uint Action;struct;uint OldMask;handle OldhItem;uint OldState;uint OldStateMask;" & _ "ptr OldText;int OldTextMax;int OldImage;int OldSelectedImage;int OldChildren;lparam OldParam;endstruct;" & _ "struct;uint NewMask;handle NewhItem;uint NewState;uint NewStateMask;" & _ "ptr NewText;int NewTextMax;int NewImage;int NewSelectedImage;int NewChildren;lparam NewParam;endstruct;" & _ "struct;long PointX;long PointY;endstruct", $lParam) Local $hWndFrom = DllStructGetData($tStruct, "hWndFrom") Local $hItem = DllStructGetData($tStruct, "NewhItem") Local $cItem = DllStructGetData($tStruct, "NewParam") Local $iCode = DllStructGetData($tStruct, "Code") If $hWndFrom = $g_hCFF_TreeView Then ; Set flag for TreeView actioned $g_bCFF_TV_Active = True ; Clear list selection DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $g_hCFF_List, "uint", 0x0186, "wparam", -1, "lparam", 0) ; $LB_SETCURSEL ; Check action Switch $iCode Case -2 ; $NM_CLICK ; Fire the dummy control GUICtrlSendToDummy($g_cCFF_Click_Dummy) Case -3 ; $NM_DBLCLK 0xFFFFFFFD ; Fire the dummy control GUICtrlSendToDummy($g_cCFF_DblClk_Dummy) ; Set flag Case $TVN_ITEMEXPANDEDW, $TVN_ITEMEXPANDEDA ; Check autoexpansion flag is not set If Not $g_bCFF_AutoExpand Then ; If expanding If DllStructGetData($tStruct, "Action") = 2 Then ; Store item data $g_hCFF_Expand_Handle = $hItem $g_cCFF_Expand_CID = $cItem ; Fire the dummy control GUICtrlSendToDummy($g_cCFF_Expand_Dummy) EndIf EndIf Case $TVN_SELCHANGEDA, $TVN_SELCHANGEDW ; Store item data $g_hCFF_Select_Handle = $hItem ; Fire the dummy control GUICtrlSendToDummy($g_cCFF_Select_Dummy) EndSwitch Else If $iCode = 0xFFFFFB20 Then ; $BCN_DROPDOWN ; Show Refresh menu option __CFF_Dropdown_Menu(DllStructGetData($tStruct, "hWndFrom")) EndIf EndIf EndFunc ;==>_CFF_WM_NOTIFY_Handler ; #FUNCTION# ========================================================================================================= ; Name...........: _CFF_WM_COMMAND_Handler ; Description ...: Windows message handler for WM_COMMAND - reacts to list getting focus ; Syntax.........: _CFF_WM_COMMAND_Handler($hWnd, $iMsg, $wParam, $lParam) ; Requirement(s).: v3.3 + ; Return values..: None ; Author ........: Melba23 ; Modified ......: ; Remarks .......: If a WM_COMMAND handler already registered, then call this function from within that handler ; Example........: Yes ;===================================================================================================================== Func _CFF_WM_COMMAND_Handler($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg ; If list actioned If $lParam = $g_hCFF_List Then ; If item selected If BitShift($wParam, 16) = 0x0001 Then ; $LBN_SELCHANGE ; Clear flag $g_bCFF_TV_Active = False EndIf EndIf EndFunc ;==>_CFF_WM_COMMAND_Handler ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __CFF_List_Drives ; Description ...: Creates lists of available drives if no path is set ; Author ........: Melba23 ; Remarks .......: ; =============================================================================================================================== Func __CFF_List_Drives($sDrives, ByRef $aAll_Drives, ByRef $aNetwork_Drives, ByRef $iAll_Error, ByRef $iNetwork_Error) ; Check if drive list set If $sDrives Then ; Create array of these drives $aAll_Drives = StringSplit($sDrives, "") For $i = 1 To $aAll_Drives[0] $aAll_Drives[$i] &= ":" Next Else ; Get array of drives $aAll_Drives = DriveGetDrive("ALL") If @error Then $iAll_Error = 1 EndIf EndIf ; Get array of network drives - to show indexing label if required $aNetwork_Drives = DriveGetDrive("NETWORK") If @error Then $iNetwork_Error = 1 EndIf EndFunc ;==>__CFF_List_Drives ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: _CFF_Combo_Fill ; Description ...: Creates and fills a combo for drive selection. ; Author ........: Melba23 ; Remarks .......: ; =============================================================================================================================== Func __CFF_Fill_Combo($iW, $sDrives, ByRef $sDefDrive, ByRef $cDrive_Combo) Local $iInset = Int(($iW - 125) / 2), $aDrives ; Create drive array If $sDrives Then ; Use specified drive list $aDrives = StringSplit($sDrives, "") For $i = 1 To $aDrives[0] $aDrives[$i] &= ":" Next Else ; If no drives specified then list all $aDrives = DriveGetDrive("ALL") EndIf ; Create drive list for combo $sDrives = "" For $i = 1 To $aDrives[0] ; Only display ready drives If DriveStatus($aDrives[$i] & '\') == "READY" Then $sDrives &= StringUpper($aDrives[$i]) & "|" Else ; If default drive not ready If $sDefDrive = $aDrives[$i] Then ; Clear it $sDefDrive = "" EndIf EndIf Next ; Create combo if required If $cDrive_Combo = 9999 Then GUICtrlCreateLabel("Select Drive:", $iInset, 15, 65, 20) $cDrive_Combo = GUICtrlCreateCombo("", 65 + $iInset, 10, 50, 20) EndIf ; Set combo data GUICtrlSetData($cDrive_Combo, "|" & $sDrives, $sDefDrive) Return $cDrive_Combo EndFunc ;==>__CFF_Fill_Combo ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __CFF_Fill_Drives ; Description ...: Fills a TreeView with ready drives ; Author ........: Melba23 ; Remarks .......: ; =============================================================================================================================== Func __CFF_Fill_Drives($cTV, $aAll_Drives, $sDefDrive, $sDefFolder, $bDeepest, $bNoFolderCheck) Local $hTV, $cItem ; Check if native or UDF TV Local $bNative_TV = True If IsHWnd($cTV) Then $bNative_TV = False $hTV = $cTV Else $hTV = GUICtrlGetHandle($cTV) EndIf Local $sDrive, $cDefDriveItem = 0, $hItem _GUICtrlTreeView_BeginUpdate($hTV) For $i = 1 To $aAll_Drives[0] ; Extract drive $sDrive = $aAll_Drives[$i] ; Only display ready drives If DriveStatus($sDrive & '\') == "READY" Then If $bNative_TV Then $cItem = GUICtrlCreateTreeViewItem(StringUpper($sDrive), $cTV) GUICtrlCreateTreeViewItem("", $cItem) If $sDrive = $sDefDrive Then $cDefDriveItem = $cItem * -1 EndIf $hItem = GUICtrlGetHandle($cItem) Else $hItem = _GUICtrlTreeView_Add($hTV, $cTV, StringUpper($sDrive)) _GUICtrlTreeView_AddChild($hTV, $hItem, "") If $sDrive = $sDefDrive Then $cDefDriveItem = $cItem EndIf EndIf EndIf ; Check if only files selectable and no precheck If $bNoFolderCheck Then ; Hide folder checkboxes _GUICtrlTreeView_SetStateImageIndex($hTV, $hItem, 0) EndIf ; Check for PreCheck drives If IsArray($g_aCFF_PreCheck) Then ; Loop through array For $j = 0 To UBound($g_aCFF_PreCheck) - 1 ; Check if item is part of a precheck path If StringRegExp($g_aCFF_PreCheck[$j], "(?i)^" & $sDrive & "\\") Then ; Set checked if deepest flag set If $bDeepest Then _GUICtrlTreeView_SetChecked($hTV, $hItem) EndIf ; Check for complete match If StringRegExp($g_aCFF_PreCheck[$j], "(?i)^" & $sDrive & "\\$") Then ; If so then check and remove from list _GUICtrlTreeView_SetChecked($hTV, $hItem) $g_aCFF_PreCheck[$j] = "" EndIf ; No point in looking further ExitLoop EndIf Next EndIf Next ; Expand default drive if set - but not if definded folder also set If $cDefDriveItem And Not $sDefFolder Then If $cDefDriveItem < 0 Then ; Convert ControlID to handle $cDefDriveItem = GUICtrlGetHandle($cDefDriveItem * -1) EndIf ; Fire expansion $g_hCFF_Expand_Handle = $cDefDriveItem GUICtrlSendToDummy($g_cCFF_Expand_Dummy) _GUICtrlTreeView_Expand($hTV, $cDefDriveItem) EndIf _GUICtrlTreeView_EndUpdate($hTV) EndFunc ;==>__CFF_Fill_Drives ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __CFF_Fill_Branch ; Description ...: Fills a TreeView branch with folders and files on expansion ; Author ........: Melba23 ; Remarks .......: ; =============================================================================================================================== Func __CFF_Fill_Branch($cTV, $cParent, $sPath, $iDisplay, $sMask, $bShowExt, $iHideHS, $aNetwork_Drives, $bDeepest, $bNoFolderCheck) Local $hTV, $sFolder_Mask, $sItem, $cItem, $hSearch, $aFill_Ret[3] = [False, 0, 0], $sTree, $aContent ; Check if network drive Local $sDrive = StringLeft($sPath, 2) If IsArray($aNetwork_Drives) Then For $i = 1 To $aNetwork_Drives[0] If $aNetwork_Drives[$i] = $sDrive Then Local $aTV_Pos = WinGetPos(GUICtrlGetHandle($cTV)) SplashTextOn("", "Indexing from" & @CRLF & "Network drive..." & @CRLF & @CRLF & "Please be patient", $aTV_Pos[2], $aTV_Pos[3], $aTV_Pos[0], $aTV_Pos[1], 33) EndIf Next EndIf ; Check if native or UDF TV Local $bNative_TV = True If IsHWnd($cTV) Then $bNative_TV = False $hTV = $cTV Else $hTV = GUICtrlGetHandle($cTV) EndIf ; Store parent handle for eventual scroll if only files found If IsHWnd($cParent) Then $aFill_Ret[1] = $cParent Else $aFill_Ret[1] = GUICtrlGetHandle($cParent) EndIf ; Force path with trailing \ If StringRight($sPath, 1) <> "\" Then $sPath &= "\" EndIf ; Change seperator character for possible tree returns Local $sOldSep = Opt("GUIDataSeparatorChar", "\") ; Expand TV _GUICtrlTreeView_BeginUpdate($hTV) ; Search for folders if required Switch $iDisplay Case 0, 2, 3 ; Set mask for folder search $sFolder_Mask = $sMask ; This is valid for folder only search If $iDisplay = 0 Then ; For file and folder search look for a folder_Exclude parameter Local $aMaskSplit = StringSplit($sMask, "|") If $aMaskSplit[0] = 3 Then ; And use it if found $sFolder_Mask = "*|" & $aMaskSplit[3] Else $sFolder_Mask = "*" EndIf EndIf ; Now list folders $aContent = _FileListToArrayRec($sPath, $sFolder_Mask, 2 + $iHideHS, 0, 1, 1) If IsArray($aContent) Then For $i = 1 To $aContent[0] ; Remove trailing \ if needed $sItem = $aContent[$i] If StringRight($sItem, 1) = "\" Then $sItem = StringTrimRight($sItem, 1) EndIf ; Create item If $bNative_TV Then $cItem = GUICtrlCreateTreeViewItem($sItem, $cParent) ; Store handle for possible scroll $aFill_Ret[1] = GUICtrlGetHandle($cItem) Else ; Use correct function depending on TV type If $cParent = $hTV Then $cItem = _GUICtrlTreeView_Add($hTV, $cParent, $sItem) Else $cItem = _GUICtrlTreeView_AddChild($hTV, $cParent, $sItem) EndIf ; Store handle for possible scroll $aFill_Ret[1] = $cItem EndIf ; Check if only files selectable and no precheck If $bNoFolderCheck Then ; Hide folder checkboxes _GUICtrlTreeView_SetStateImageIndex($hTV, $aFill_Ret[1], 0) EndIf ; Check for PreCheck folders If IsArray($g_aCFF_PreCheck) Then ; Get full tree of the item $sTree = $sPath & StringRegExpReplace(_GUICtrlTreeView_GetTree($hTV, $aFill_Ret[1]), ".*\\(.+)", "$1") ; Escape special SRE characters $sTree = StringRegExpReplace($sTree, "[][$^.{}()+\\-]", "\\$0") ; Loop through array For $j = 0 To UBound($g_aCFF_PreCheck) - 1 ; Check if item is part of a precheck path If StringRegExp($g_aCFF_PreCheck[$j], "(?i)^" & $sTree & "\\") Then ; Set checked if deepest flag set If $bDeepest Then _GUICtrlTreeView_SetChecked($hTV, $aFill_Ret[1]) EndIf ; Check for complete match If StringRegExp($g_aCFF_PreCheck[$j], "(?i)^" & $sTree & "\\$") Then ; If so then check and remove from list _GUICtrlTreeView_SetChecked($hTV, $aFill_Ret[1]) $g_aCFF_PreCheck[$j] = "" EndIf ; No point in looking further ExitLoop EndIf Next EndIf ; Check for refreshed folders If IsArray($g_aCFF_Checked_Retain) Then ; Array exists ; Get full tree of the item $sTree = $sPath & StringRegExpReplace(_GUICtrlTreeView_GetTree($hTV, $aFill_Ret[1]), ".*\\(.+)", "$1") ; Escape special SRE characters $sTree = StringRegExpReplace($sTree, "[][$^.{}()+\\-]", "\\$0") ; Loop through array For $j = 0 To UBound($g_aCFF_Checked_Retain) - 1 ; Check if item is part of a precheck path If StringRegExp($g_aCFF_Checked_Retain[$j], "(?i)^" & $sTree & "\\") Then ; Set checked if deepest flag set If $bDeepest Then _GUICtrlTreeView_SetChecked($hTV, $aFill_Ret[1]) EndIf ; Check for complete match If StringRegExp($g_aCFF_Checked_Retain[$j], "(?i)^" & $sTree & "\\$") Then ; If so then check and remove from list _GUICtrlTreeView_SetChecked($hTV, $aFill_Ret[1]) $g_aCFF_Checked_Retain[$j] = "" EndIf ; No point in looking further ExitLoop EndIf Next EndIf ; Force a [+] if suitable content within FileChangeDir($sPath & $aContent[$i]) $hSearch = FileFindFirstFile("*") ; If there is something within If $hSearch <> -1 Then ; Set flag $aFill_Ret[0] = True ; Different display modes require different content types Switch $iDisplay Case 0 ; Either folder or file ; Create dummy child to force [+] display If $bNative_TV Then GUICtrlCreateTreeViewItem("", $cItem) Else _GUICtrlTreeView_AddChild($hTV, $cItem, "") EndIf ; Case 1 ; Files only so no requirement for [+] Case 2, 3 ; Folder only While 1 ; Search for a folder FileFindNextFile($hSearch) ; End of content If @error Then ExitLoop EndIf ; If folder found If @extended Then ; Create dummy child to force [+] display If $bNative_TV Then GUICtrlCreateTreeViewItem("", $cItem) Else _GUICtrlTreeView_AddChild($hTV, $cItem, "") EndIf ; No need to look further ExitLoop EndIf WEnd ; Close search FileClose($hSearch) EndSwitch EndIf ; Reset working folder FileChangeDir(@ScriptDir) Next EndIf EndSwitch ; Search for files if required Switch $iDisplay Case 0, 1 ; List files $aContent = _FileListToArrayRec($sPath, $sMask, 1 + $iHideHS, 0, 1) If IsArray($aContent) Then ; Set flag $aFill_Ret[0] = True For $i = 1 To $aContent[0] $sItem = $aContent[$i] ; Remove extension if required If Not $bShowExt Then $sItem = StringRegExpReplace($sItem, "(.*)\..*", "$1") EndIf ; Create item If $bNative_TV Then $cItem = GUICtrlCreateTreeViewItem($sItem, $cParent) ; Store handle for possible scroll $aFill_Ret[2] = GUICtrlGetHandle($cItem) Else ; Use correct function depending on TV type If $cParent = $hTV Then $cItem = _GUICtrlTreeView_Add($hTV, $cParent, $sItem) Else $cItem = _GUICtrlTreeView_AddChild($hTV, $cParent, $sItem) EndIf ; Store handle for possible scroll $aFill_Ret[2] = $cItem EndIf ; Check for PreCheck files If IsArray($g_aCFF_PreCheck) Then ; Get full tree of the item $sTree = $sPath & StringRegExpReplace(_GUICtrlTreeView_GetTree($hTV, $aFill_Ret[2]), ".*\\(.+)", "$1") ; Loop through the list For $j = 0 To UBound($g_aCFF_PreCheck) - 1 ; If there is a match If $g_aCFF_PreCheck[$j] = $sTree Then ; Set checkbox _GUICtrlTreeView_SetChecked($hTV, $aFill_Ret[2]) ; Delete from list $g_aCFF_PreCheck[$j] = "" ; No point in continuing ExitLoop EndIf Next EndIf ; Check for refreshed files If IsArray($g_aCFF_Checked_Retain) Then ; Array exists ; Get full tree of the item $sTree = $sPath & StringRegExpReplace(_GUICtrlTreeView_GetTree($hTV, $aFill_Ret[2]), ".*\\(.+)", "$1") ; Loop through the list For $j = 0 To UBound($g_aCFF_Checked_Retain) - 1 ; If there is a match If $g_aCFF_Checked_Retain[$j] = $sTree Then ; Set checkbox _GUICtrlTreeView_SetChecked($hTV, $aFill_Ret[2]) ; Delete from list $g_aCFF_Checked_Retain[$j] = "" ; No point in continuing ExitLoop EndIf Next EndIf Next EndIf EndSwitch _GUICtrlTreeView_EndUpdate($hTV) ; Reset separator Opt("GUIDataSeparatorChar", $sOldSep) ; Hide Splash if used SplashOff() Return $aFill_Ret EndFunc ;==>__CFF_Fill_Branch ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __CFF_AutoExpand ; Description ...: Expand tree to defined folder on start ; Author ........: Melba23 ; Remarks .......: ; =============================================================================================================================== Func __CFF_AutoExpand($hTreeView, $iDisplay, $sMask, $bShowExt, $iHideHS, $aNetwork_Drives, $sDefFolder, $bDefFolder_Open, $iRedraw_Count, $bDeepest, $bNoFolderCheck, $bCombo = False, $bNative_TV = False) Local $aDefFolder_Split, $iDefFolder_Start = 1, $hDefFolder_Item, $vParent_Item, $sDefExpand_Path = "" ; Set flag to prevent expansion dummy firing $g_bCFF_AutoExpand = True ; Split path into elements $aDefFolder_Split = StringSplit($sDefFolder, "\") ; Set up counter - miss drive element if not in treeview If $bCombo Then $iDefFolder_Start = 2 $sDefExpand_Path = StringReplace($aDefFolder_Split[1], "_", " ") & "\" EndIf ; Get initial handle to start process $hDefFolder_Item = _GUICtrlTreeView_GetFirstItem($hTreeView) ; Look for required folder For $i = $iDefFolder_Start To $aDefFolder_Split[0] ; Set required path $sDefExpand_Path &= StringReplace($aDefFolder_Split[$i], "_", " ") & "\" ; Look for required folder Do If _GUICtrlTreeView_GetText($hTreeView, $hDefFolder_Item) = $aDefFolder_Split[$i] Then ExitLoop EndIf $hDefFolder_Item = _GUICtrlTreeView_GetNextSibling($hTreeView, $hDefFolder_Item) Until $hDefFolder_Item = 0 ; Ensure visible and selected _GUICtrlTreeView_EnsureVisible($hTreeView, $hDefFolder_Item) _GUICtrlTreeView_ClickItem($hTreeView, $hDefFolder_Item) ; Check if final folder is to be expanded If (Not $bDefFolder_Open) And $i = $aDefFolder_Split[0] Then ExitLoop EndIf ; Expand folder _GUICtrlTreeView_Expand($hTreeView, $hDefFolder_Item) ; Get ControlID/handle for parent If $bNative_TV Then ; Short sleep for native ListViews internal processing - increasing with redraws Sleep(50 * $iRedraw_Count) $vParent_Item = GUICtrlRead($hTreeView) Else $vParent_Item = $hDefFolder_Item EndIf ; Fill branch __CFF_Fill_Branch($hTreeView, $vParent_Item, $sDefExpand_Path, $iDisplay, $sMask, $bShowExt, $iHideHS, $aNetwork_Drives, $bDeepest, $bNoFolderCheck) ; Check for content - final folder may be empty If _GUICtrlTreeView_GetChildCount($hTreeView, $hDefFolder_Item) > 0 Then ; Delete existing first blank child _GUICtrlTreeView_Delete($hTreeView, _GUICtrlTreeView_GetFirstChild($hTreeView, $hDefFolder_Item)) ; Get new first item $hDefFolder_Item = _GUICtrlTreeView_GetFirstChild($hTreeView, $hDefFolder_Item) EndIf Next ; Clear flag to re-enable expand dummy $g_bCFF_AutoExpand = False EndFunc ;==>__CFF_AutoExpand ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __CFF_File_Visible ; Description ...: Ensure files visible if selecting files only and displaying both files and folders ; Author ........: Melba23 ; Remarks .......: ; =============================================================================================================================== Func __CFF_File_Visible($hTreeView, $aFill_Ret) ; Last file visible _GUICtrlTreeView_EnsureVisible($hTreeView, $aFill_Ret[2]) ; Last folder visible - first file immediately follows _GUICtrlTreeView_EnsureVisible($hTreeView, $aFill_Ret[1]) EndFunc ;==>__CFF_File_Visible ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __CFF_Check_Display ; Description ...: Checks for valid Display parameter ; Author ........: Melba23 ; Remarks .......: ; =============================================================================================================================== Func __CFF_Check_Display($iDisplay, $sFile_Mask, ByRef $aFlags) ; Show hidden and system files If BitAND($iDisplay, 4) Then $aFlags[$g_eCFF_HideHS] += 4 $iDisplay -= 4 EndIf If BitAND($iDisplay, 8) Then $aFlags[$g_eCFF_HideHS] += 8 $iDisplay -= 8 EndIf ; Both files and folders selectable If BitAND($iDisplay, 16) Then $aFlags[$g_eCFF_BothSelectable] = True $iDisplay -= 16 EndIf ; Allow duplicate selections If BitAND($iDisplay, 32) Then $aFlags[$g_eCFF_DuplicatesAllowed] = True $iDisplay -= 32 EndIf ; Hide file extensions? If BitAND($iDisplay, 64) Then $iDisplay -= 64 ; Check that only one ext is specified StringReplace($sFile_Mask, ";", "") Local $iExt = @extended If $sFile_Mask <> "*.*" And $iExt = 0 Then ; File exts hidden $aFlags[$g_eCFF_ShowExt] = False EndIf EndIf ; Scroll to first file If BitAND($iDisplay, 128) Then $aFlags[$g_eCFF_FileScroll] = True $iDisplay -= 128 EndIf ; Display splashscreens If BitAND($iDisplay, 256) Then $aFlags[$g_eCFF_ShowSplash] = True $iDisplay -= 256 EndIf ; Only return deepest checked If BitAND($iDisplay, 512) Then $aFlags[$g_eCFF_OnlyReturnDeepest] = True $iDisplay -= 512 EndIf ; Drive list refresh allowed If BitAND($iDisplay, 1024) Then $aFlags[$g_eCFF_AllowRefresh] = True $iDisplay -= 1024 EndIf ; Check valid parameter Switch $iDisplay Case 0 To 3 Return $iDisplay Case Else Return SetError(1, 0, 0) EndSwitch EndFunc ;==>__CFF_Check_Display ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __CFF_Verify_PreCheck ; Description ...: Checks for valid pre-check array elements ; Author ........: Melba23 ; Remarks .......: ; =============================================================================================================================== Func __CFF_Verify_PreCheck(ByRef $g_aCFF_PreCheck, $iDisplay, $bBoth_Selectable) Local $sPath, $sAttribs For $i = 0 To UBound($g_aCFF_PreCheck) - 1 ; Extract item $sPath = $g_aCFF_PreCheck[$i] ; Get Item sttribs $sAttribs = FileGetAttrib($sPath) If @error Then ; Invalid path $sPath = "" ; No point in continuing ContinueLoop EndIf Switch $iDisplay Case 0 ; Files only - unless both selectable flag set If StringInStr($sAttribs, "D") Then If $bBoth_Selectable Then ; Add a trailing \ if required If StringRight($sPath, 1) <> "\" Then $sPath &= "\" Else ; Remove from list $sPath = "" EndIf EndIf Case 1 ; Files only If StringInStr($sAttribs, "D") Then ; Remove from list $sPath = "" EndIf Case 2, 3 ; Folders only If StringInStr($sAttribs, "D") Then ; Add a trailing \ if required If StringRight($sPath, 1) <> "\" Then $sPath &= "\" Else ; Remove from list $sPath = "" EndIf EndSwitch Next EndFunc ;==>__CFF_Verify_PreCheck ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: _CFF_Check_Valid ; Description ...: Checks selection is valid ; Author ........: Melba23 ; Remarks .......: ; =============================================================================================================================== Func __CFF_Check_Selection($cTV, $hItem, $sRoot, $iDisplay, $bBoth_Selectable, $bShowExt, $sFile_Mask) ; Get tree path of selected item Local $sSelectedItem = StringReplace(_GUICtrlTreeView_GetTree($cTV, $hItem), "|", "\") If $sSelectedItem = "" Then ; Nothing selected Return "" EndIf ; Convert to full path Local $sSelectedPath = $sRoot & $sSelectedItem Switch $iDisplay Case 0 ; Files and folders displayed ; Check if folder by looking at attributes StringReplace(FileGetAttrib($sSelectedPath), "D", "") If @extended Then ; Are folders selectable? If $bBoth_Selectable Then ; Add trailing \ $sSelectedPath &= "\" Else ; Reject selection $sSelectedPath = "" EndIf Else ; File so check extension display ContinueCase EndIf Case 1 ; Only files displayed ; Hide extension? If $bShowExt = False Then $sSelectedPath &= StringTrimLeft($sFile_Mask, 1) EndIf ;Case 2, 3 ; Only folders displayed EndSwitch Return $sSelectedPath EndFunc ;==>__CFF_Check_Selection ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __CFF_ParseTV ; Description ...: Gets current TV checkbox state ; Author ........: Melba23 ; =============================================================================================================================== Func __CFF_ParseTV($hTV) ; Basic check data array and item count Local $aParseTV[10][3], $iParseCount = 0 ; Work through TreeView items Local $hHandle = _GUICtrlTreeView_GetFirstItem($hTV) While 1 ; Add item to array $aParseTV[$iParseCount][0] = $hHandle $aParseTV[$iParseCount][1] = _GUICtrlTreeView_GetChecked($hTV, $hHandle) $aParseTV[$iParseCount][2] = _GUICtrlTreeView_GetText($hTV, $hHandle) ; Increase count $iParseCount += 1 ; Enlarge array if required (minimizes ReDim usage) If $iParseCount > UBound($aParseTV) - 1 Then ReDim $aParseTV[$iParseCount * 2][3] EndIf ; Move to next item $hHandle = _GUICtrlTreeView_GetNext($hTV, $hHandle) ; Exit if at end If $hHandle = 0 Then ExitLoop WEnd ; Remove any empty array elements ReDim $aParseTV[$iParseCount][3] Return $aParseTV EndFunc ;==>__CFF_ParseTV ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __CFF_Checked_List ; Description ...: Creates array of checked items to be retained during a refresh ; Author ........: Melba23 ; =============================================================================================================================== Func __CFF_Checked_List($hTV) Local $aCheckedItems[10], $iCount = 0 ; Work through TreeView items Local $hHandle = _GUICtrlTreeView_GetFirstItem($hTV) While 1 ; If checked If _GUICtrlTreeView_GetChecked($hTV, $hHandle) Then ; Add to array $aCheckedItems[$iCount] = StringReplace(_GUICtrlTreeView_GetTree($hTV, $hHandle), "|", "\") ; Increase count $iCount += 1 ; Enlarge array if required (minimizes ReDim usage) If $iCount > UBound($aCheckedItems) - 1 Then ReDim $aCheckedItems[$iCount * 2] EndIf EndIf ; Move to next item $hHandle = _GUICtrlTreeView_GetNext($hTV, $hHandle) ; Exit if at end If $hHandle = 0 Then ExitLoop WEnd ; Remove unfilled elements ReDim $aCheckedItems[$iCount] Return $aCheckedItems EndFunc ;==>__CFF_Checked_List ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __CFF_Adjust_Parents ; Description ...: Adjusts checkboxes above the one changed ; Author ........: Melba23 ; =============================================================================================================================== Func __CFF_Adjust_Parents($hTV, $hPassedItem, ByRef $aTVCheckData, $bState = True) ; Get handle of parent Local $hParent = _GUICtrlTreeView_GetParentHandle($hTV, $hPassedItem) If $hParent = 0 Then Return ; Assume parent is to be adjusted Local $bAdjustParent = True ; Find parent in array Local $iItemIndex = _ArraySearch($aTVCheckData, $hParent) ; Need to confirm all siblings clear before clearing parent If $bState = False Then ; Check on number of siblings Local $iCount = _GUICtrlTreeView_GetChildCount($hTV, $hParent) ; If only 1 sibling then parent can be cleared - if more then need to look at them all If $iCount <> 1 Then ; Number of siblings checked Local $iCheckCount = 0 ; Move through previous siblings Local $hSibling = $hPassedItem While 1 $hSibling = _GUICtrlTreeView_GetPrevSibling($hTV, $hSibling) ; If found If $hSibling Then ; Is sibling checked) If _GUICtrlTreeView_GetChecked($hTV, $hSibling) Then ; Increase count if so $iCheckCount += 1 EndIf Else ; No point in continuing ExitLoop EndIf WEnd ; Move through later siblings $hSibling = $hPassedItem While 1 $hSibling = _GUICtrlTreeView_GetNextSibling($hTV, $hSibling) If $hSibling Then If _GUICtrlTreeView_GetChecked($hTV, $hSibling) Then $iCheckCount += 1 EndIf Else ExitLoop EndIf WEnd ; If at least one sibling checked then do not clear parent If $iCheckCount Then $bAdjustParent = False EndIf EndIf ; If parent is to be adjusted If $bAdjustParent Then ; Adjust the array $aTVCheckData[$iItemIndex][1] = $bState ; Adjust the parent _GUICtrlTreeView_SetChecked($hTV, $hParent, $bState) ; And now do the same for the generation above __CFF_Adjust_Parents($hTV, $hParent, $aTVCheckData, $bState) EndIf EndFunc ;==>__CFF_Adjust_Parents ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __CFF_Adjust_Children ; Description ...: Adjusts checkboxes below the one changed ; Author ........: Melba23 ; =============================================================================================================================== Func __CFF_Adjust_Children($hTV, $hPassedItem, ByRef $aTVCheckData, $bState = True) Local $iItemIndex ; Get the handle of the first child Local $hChild = _GUICtrlTreeView_GetFirstChild($hTV, $hPassedItem) If $hChild = 0 Then Return While 1 ; Find child index $iItemIndex = _ArraySearch($aTVCheckData, $hChild) If Not @error Then ; Adjust the array $aTVCheckData[$iItemIndex][1] = $bState ; Adjust the child _GUICtrlTreeView_SetChecked($hTV, $hChild, $bState) ; And now do the same for the generation beow __CFF_Adjust_Children($hTV, $hChild, $aTVCheckData, $bState) ; Now get next child $hChild = _GUICtrlTreeView_GetNextChild($hTV, $hChild) ; Exit the loop if no more found If $hChild = 0 Then ExitLoop EndIf WEnd EndFunc ;==>__CFF_Adjust_Children ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __CFF_List_Add ; Description ...: Adds item to return list ; Author ........: Melba23 ; Remarks .......: ; =============================================================================================================================== Func __CFF_List_Add($sAddFile_List, $sSelectedPath, $cList, $bDuplicates_Allowed, $cTreeView) ; Check for existing instance in list If StringInStr($sAddFile_List, $sSelectedPath & "|") Then ; If duplicates are allowed If $bDuplicates_Allowed Then ; Add to return string $sAddFile_List &= $sSelectedPath & "|" ; Add to onscreen list GUICtrlSendMsg($cList, 0x0180, 0, $sSelectedPath) ; $LB_ADDSTRING EndIf Else ; Add to return string $sAddFile_List &= $sSelectedPath & "|" ; Add to onscreen list GUICtrlSendMsg($cList, 0x0180, 0, $sSelectedPath) ; $LB_ADDSTRING EndIf ; Scroll to bottom of list GUICtrlSendMsg($cList, 0x197, GUICtrlSendMsg($cList, 0x18B, 0, 0) - 1, 0) ; $LB_SETTOPINDEX, $LB_GETCOUNT ; Return focus to TV GUICtrlSetState($cTreeView, 256) ; $GUI_FOCUS Return $sAddFile_List EndFunc ;==>__CFF_List_Add ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __CFF_List_Del ; Description ...: Deletes item from return list ; Author ........: Melba23 ; Remarks .......: ; =============================================================================================================================== Func __CFF_List_Del($sAddFile_List, $sSelectedPath, $cList, $cTreeView) Local $iTopIndex = 9999 ; Check for existing instance in list If StringInStr($sAddFile_List, $sSelectedPath & "|") Then ; Delete last instance of item $sAddFile_List = StringReplace($sAddFile_List, $sSelectedPath & "|", "", -1) ; Get current scroll position if list selection If Not $g_bCFF_TV_Active Then ; Get current top index $iTopIndex = GUICtrlSendMsg($cList, 0x018E, 0, 0) ; $LB_GETTOPINDEX EndIf ; Replace list content with new list GUICtrlSetData($cList, "|" & $sAddFile_List) EndIf ; Scroll as required If $iTopIndex <> 9999 Then ; Scroll to same place if list selection GUICtrlSendMsg($cList, 0x197, $iTopIndex, 0) ; $LB_SETTOPINDEX Else ; Scroll to bottom of list if treeview selection GUICtrlSendMsg($cList, 0x197, GUICtrlSendMsg($cList, 0x18B, 0, 0) - 1, 0) ; $LB_SETTOPINDEX, $LB_GETCOUNT EndIf ; Return focus to TV GUICtrlSetState($cTreeView, 256) ; $GUI_FOCUS Return $sAddFile_List EndFunc ;==>__CFF_List_Del ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __CFF_Dropdown_Menu ; Description ...: Creates menu for Cancel split button ; Author ........: Melba23 ; Remarks .......: ; =============================================================================================================================== Func __CFF_Dropdown_Menu($hCtrl) Local Enum $iOption_1 = 1000, $iOption_2 Local $hMenu = _GUICtrlMenu_CreatePopup() _GUICtrlMenu_InsertMenuItem($hMenu, 0, "Cancel", $iOption_1) _GUICtrlMenu_InsertMenuItem($hMenu, 1, "Refresh", $iOption_2) Switch _GUICtrlMenu_TrackPopupMenu($hMenu, $hCtrl, -1, -1, 1, 1, 2) Case $iOption_1 ; Cancel GUICtrlSendToDummy($g_cCFF_Esc_Dummy) Case $iOption_2 ; Refresh GUICtrlSendToDummy($g_cCFF_Refresh_Dummy) EndSwitch _GUICtrlMenu_DestroyMenu($hMenu) EndFunc ;==>__CFF_Dropdown_Menu