sl23 Posted September 15 Posted September 15 (edited) Simple as that really. I have a treeview set up in a settings gui. I would like to be able use a right click to auto select the item before proceeding with the context menu and selecting Delete. Essentially I want to perform these actions on Right clicking a treeview item: $GUI_EVENT_PRIMARYDOWN then $GUI_EVENT_SECONDARYUP all in one right click action. I tried this in the handler, but it isn't working: Case $g_AppMenuDeleteItem MouseClick("left") Sleep(50) _AppTab_DeleteSelected() Also tried this: ; --- Right-click: select item under mouse before showing context menu --- If $msg = $GUI_EVENT_SECONDARYDOWN Then Local $cursor = GUIGetCursorInfo($hGUI) Local $ctrlPos = ControlGetPos($hGUI, "", $g_AppTreeView) If IsArray($cursor) And IsArray($ctrlPos) Then Local $relX = $cursor[0] - $ctrlPos[0] Local $relY = $cursor[1] - $ctrlPos[1] Local $item = _GUICtrlTreeView_HitTest($g_AppTreeView, $relX, $relY) If $item > 0 Then GUICtrlSendMsg($g_AppTreeView, $TVM_SELECTITEM, $TVGN_CARET, $item) $g_AppLastSelectedItem = $item EndIf EndIf EndIf Can't get it to work. Is it even possible? Thanks for your help. Edited September 15 by sl23
sl23 Posted September 15 Author Posted September 15 Just tried moving the left click code to a function and calling it, but it refuses to change selection on richt click! there must be a way? expandcollapse popupFunc Tab_App_HandleEvents($msg) Local $selectedItem = GUICtrlRead($g_AppTreeView) ; Handle buttons and context menu Switch $msg Case $g_SaveBtn If $g_SelectedIni <> "" And $g_SelectedSection <> "" Then _AppTab_SaveFields($g_SelectedIni, $g_SelectedSection) EndIf Case $g_IgnoreBtn _AppTab_IgnoreSelected() Case $g_AppMenuDeleteItem _AppTab_HandleSelectionChange($selectedItem) ;~ MouseClick("left") ;~ Sleep(50) _AppTab_DeleteSelected() Case $g_AppFields("SymLinkCreate") ; Enable/disable symlinks field based on checkbox If GUICtrlRead($g_AppFields("SymLinkCreate")) = $GUI_CHECKED Then GUICtrlSetState($g_AppsSymlinksEdit, $GUI_ENABLE) Else GUICtrlSetState($g_AppsSymlinksEdit, $GUI_DISABLE) EndIf Case $g_AppFields("Sandboxie") ; Enable/disable SandboxName field based on checkbox If GUICtrlRead($g_AppFields("Sandboxie")) = $GUI_CHECKED Then GUICtrlSetState($g_AppFields("SandboxName"), $GUI_ENABLE) Else GUICtrlSetState($g_AppFields("SandboxName"), $GUI_DISABLE) EndIf EndSwitch _AppTab_HandleSelectionChange($selectedItem) ;~ ; Only act if the selection changed ;~ If $selectedItem <> $g_AppLastSelectedItem Then ;~ ; If a category node is selected ;~ If $selectedItem <> 0 And $g_AppCategoryTreeItems.Exists($selectedItem) Then ;~ _AppTab_ClearFields() ;~ _AppTab_DisableFields() ;~ GUICtrlSetState($g_SaveBtn, $GUI_DISABLE) ;~ GUICtrlSetState($g_IgnoreBtn, $GUI_DISABLE) ;~ $g_SelectedIni = "" ;~ $g_SelectedSection = "" ;~ ; If last selected was a valid app item and now whitespace/node: disable buttons ;~ ElseIf $g_AppLastSelectedItem <> 0 And $g_AppTreeItemToSection.Exists($g_AppLastSelectedItem) _ ;~ And ($selectedItem = 0 Or Not $g_AppTreeItemToSection.Exists($selectedItem)) Then ;~ _AppTab_ClearFields() ;~ _AppTab_Buttons_Disable() ;~ $g_SelectedIni = "" ;~ $g_SelectedSection = "" ;~ ; If selection changed to a valid app item: enable buttons ;~ ElseIf $selectedItem <> 0 And $g_AppTreeItemToSection.Exists($selectedItem) Then ;~ $g_SelectedSection = $g_AppTreeItemToSection.Item($selectedItem) ;~ $g_SelectedIni = $g_AppTreeItemToIni.Item($selectedItem) ;~ _AppTab_PopulateFields($g_SelectedIni, $g_SelectedSection) ;~ _AppTab_EnableFields() ;~ _AppTab_Buttons_Enable() ;~ ; If selection changed to whitespace/node, disable buttons ;~ Else ;~ _AppTab_ClearFields() ;~ _AppTab_Buttons_Disable() ;~ $g_SelectedIni = "" ;~ $g_SelectedSection = "" ;~ EndIf ;~ $g_AppLastSelectedItem = $selectedItem ;~ EndIf EndFunc Func _AppTab_HandleSelectionChange($selectedItem) If $selectedItem <> $g_AppLastSelectedItem Then If $selectedItem <> 0 And $g_AppCategoryTreeItems.Exists($selectedItem) Then _AppTab_ClearFields() _AppTab_DisableFields() GUICtrlSetState($g_SaveBtn, $GUI_DISABLE) GUICtrlSetState($g_IgnoreBtn, $GUI_DISABLE) $g_SelectedIni = "" $g_SelectedSection = "" ElseIf $g_AppLastSelectedItem <> 0 And $g_AppTreeItemToSection.Exists($g_AppLastSelectedItem) _ And ($selectedItem = 0 Or Not $g_AppTreeItemToSection.Exists($selectedItem)) Then _AppTab_ClearFields() _AppTab_Buttons_Disable() $g_SelectedIni = "" $g_SelectedSection = "" ElseIf $selectedItem <> 0 And $g_AppTreeItemToSection.Exists($selectedItem) Then $g_SelectedSection = $g_AppTreeItemToSection.Item($selectedItem) $g_SelectedIni = $g_AppTreeItemToIni.Item($selectedItem) _AppTab_PopulateFields($g_SelectedIni, $g_SelectedSection) _AppTab_EnableFields() _AppTab_Buttons_Enable() Else _AppTab_ClearFields() _AppTab_Buttons_Disable() $g_SelectedIni = "" $g_SelectedSection = "" EndIf $g_AppLastSelectedItem = $selectedItem EndIf EndFunc
ioa747 Posted September 15 Posted September 15 (edited) Local $idTreeview = GUICtrlCreateTreeView(6, 6, 100, 150, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS), $WS_EX_CLIENTEDGE) Local $idButtoncontext = GUICtrlCreateContextMenu($idTreeview) Local $idMenuDelete = GUICtrlCreateMenuItem("Dellete", $idButtoncontext) Switch $msg ... Case $idMenuDelete Local $hSelection = _GUICtrlTreeView_GetSelection($idTreeView) ConsoleWrite("!Dellete Selection: " & $hSelection & @CRLF) ;_GUICtrlTreeView_Delete($idTreeView, $hSelection) Edited September 15 by ioa747 I know that I know nothing
sl23 Posted September 15 Author Posted September 15 (edited) Thanks, but isn't that just a standard context menu creation for a TreeView? I need it to select first then show the context menu for delete. I currently have the context menu and it works fine. Everything is working ok. I just needed to enhance the right click by first selecting the item with the right mouse button, then open the context menu. is that possible? Ah, sorry i posted while you were in the middle of updating your post! Seems that is not what I wanted either actually. Thank you anyway. As you can see it is probably a niche thing? I have a tree view with category containing items. If I select a category then right click an item I am asked if I want to delete the category, which is a mistake and could be a major problem! So I wondered if it were possible to do the selction on right click before showing the context menu? Edited September 15 by sl23
sl23 Posted September 15 Author Posted September 15 (edited) Here is a test code. in order to test correctly, follow these instructions to see the error in the handling of the selection: 1. Run the script and select the Category using left mouse button to open it. 2. Right click any node and select delete. Notice that the message is asking if you want to delete the category, not the node you right clicked on! So what I am asking is, can I basically perform a left-click action using the right mouse click? This would then: 1. select the item. 2. Open the context menu. 3. selecting delete would then delete the correct item. Test code: expandcollapse popup#include <GUIConstantsEx.au3> #include <GuiTreeView.au3> $hGUI = GUICreate("TreeView Category Right Click Select Example", 300, 220) $idTreeview = GUICtrlCreateTreeView(10, 10, 150, 180, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_SHOWSELALWAYS)) $idMenu = GUICtrlCreateContextMenu($idTreeview) $idMenuDelete = GUICtrlCreateMenuItem("Delete", $idMenu) ; Add category node(s) Global $aCategories[1] $aCategories[0] = GUICtrlCreateTreeViewItem("Category 1", $idTreeview) ; Add child nodes under category $idItem1 = GUICtrlCreateTreeViewItem("Node 1", $aCategories[0]) $idItem2 = GUICtrlCreateTreeViewItem("Node 2", $aCategories[0]) $idItem3 = GUICtrlCreateTreeViewItem("Node 3", $aCategories[0]) GUISetState() While 1 $msg = GUIGetMsg() ; --- Hit-test for right mouse button down --- If $msg = $GUI_EVENT_SECONDARYDOWN Then $aCursor = GUIGetCursorInfo($hGUI) $aPos = ControlGetPos($hGUI, "", $idTreeview) If IsArray($aCursor) And IsArray($aPos) Then $relX = $aCursor[0] - $aPos[0] $relY = $aCursor[1] - $aPos[1] $itemID = _GUICtrlTreeView_HitTest($idTreeview, $relX, $relY) If $itemID > 0 Then GUICtrlSendMsg($idTreeview, 0x110B, 0x9, $itemID) ; Select the node under mouse EndIf EndIf EndIf Switch $msg Case $idMenuDelete $hSelection = _GUICtrlTreeView_GetSelection($idTreeview) ; Get the text of the selected node for confirmation Local $sNodeText = _GUICtrlTreeView_GetText($idTreeview, $hSelection) ; Check if selection is a category node (parent) Local $isCategory = False For $i = 0 To UBound($aCategories) - 1 If $hSelection = $aCategories[$i] Then $isCategory = True ExitLoop EndIf Next If $isCategory Then ; Confirm category deletion Local $answer = MsgBox(36, "Delete Category", "Are you sure you want to delete the CATEGORY: """ & $sNodeText & """ and all its items?") If $answer = 6 Then ; Yes _GUICtrlTreeView_Delete($idTreeview, $hSelection) EndIf ElseIf $hSelection <> 0 Then ; Confirm node deletion Local $answer = MsgBox(36, "Delete Node", "Are you sure you want to delete the NODE: """ & $sNodeText & """?") If $answer = 6 Then ; Yes _GUICtrlTreeView_Delete($idTreeview, $hSelection) EndIf EndIf Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd GUIDelete() Why is it that this doesn't work: MouseClick($MOUSE_CLICK_LEFT) Edited September 15 by sl23
Solution Nine Posted September 15 Solution Posted September 15 (edited) Here my take on it : expandcollapse popup#include <GUIConstants.au3> #include <GuiTreeView.au3> Opt("MustDeclareVars", True) Global $itemID Example() Func Example() Local $hGUI = GUICreate("TreeView Category Right Click Select Example", 300, 220) Local $idTreeview = GUICtrlCreateTreeView(10, 10, 150, 180, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_SHOWSELALWAYS)) Local $idMenu = GUICtrlCreateContextMenu($idTreeview) Local $idMenuDelete = GUICtrlCreateMenuItem("Delete", $idMenu) ; Add category node(s) Local $aCategories[1] $aCategories[0] = GUICtrlCreateTreeViewItem("Category 1", $idTreeview) ; Add child nodes under category Local $idItem1 = GUICtrlCreateTreeViewItem("Node 1", $aCategories[0]) Local $idItem2 = GUICtrlCreateTreeViewItem("Node 2", $aCategories[0]) Local $idItem3 = GUICtrlCreateTreeViewItem("Node 3", $aCategories[0]) GUISetState() GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY) Local $sNodeText, $isCategory, $answer While True Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $idMenuDelete $sNodeText = _GUICtrlTreeView_GetText($idTreeview, $itemID) ; Check if selection is a category node (parent) $isCategory = False For $i = 0 To UBound($aCategories) - 1 If $itemID = _GUICtrlTreeView_GetItemHandle($idTreeview, $aCategories[$i]) Then $isCategory = True ExitLoop EndIf Next If $isCategory Then ; Confirm category deletion $answer = MsgBox(36, "Delete Category", "Are you sure you want to delete the CATEGORY: """ & $sNodeText & """ and all its items?") Else ; Confirm node deletion $answer = MsgBox(36, "Delete Node", "Are you sure you want to delete the NODE: """ & $sNodeText & """?") EndIf If $answer = 6 Then _GUICtrlTreeView_Delete($idTreeview, $itemID) ; Yes EndSwitch WEnd EndFunc ;==>Example Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam) If $tNMHDR.code <> $NM_RCLICK Then Return $GUI_RUNDEFMSG Local $cursor = GUIGetCursorInfo($hWnd) Local $ctrlPos = ControlGetPos($hWnd, "", $tNMHDR.idFrom) Local $relX = $cursor[0] - $ctrlPos[0] Local $relY = $cursor[1] - $ctrlPos[1] $itemID = _GUICtrlTreeView_HitTestItem($wParam, $relX, $relY) If Not $itemID Then Return 1 Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY Edited September 15 by Nine “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
sl23 Posted September 16 Author Posted September 16 That test script does exactly what I was hoping, but for the life of me, I just cannot get it running correctly in my script! It either doesn't work, or it breaks some other functionality! Here's the before script: expandcollapse popup; Tab_Apps.au3 #include-once #include <GuiTreeView.au3> #include <File.au3> #include <Array.au3> Global $g_CategoryIniDir = @ScriptDir & "\App" Global $g_AppTreeView, $g_AppFields, $g_IniFiles, $g_AppSections, $g_SelectedIni, $g_SelectedSection Global $g_SaveBtn, $g_IgnoreBtn, $g_RefreshBtn Global $g_AppTreeItemToSection = ObjCreate("Scripting.Dictionary") Global $g_AppTreeItemToIni = ObjCreate("Scripting.Dictionary") Global $g_AppLastSelectedItem = 0 Global $guiW, $guiH, $listviewX, $listviewY, $btnW, $btnH, $footer_gap, $hGUI Global $g_AppCategoryTreeItems = ObjCreate("Scripting.Dictionary") Global $g_AppsSymlinksEdit Global Const $ES_MULTILINE = 0x0004 Global Const $ES_WANTRETURN = 0x1000 Global $g_AppTreeViewMenu, $g_AppMenuDeleteItem Func Tab_Apps_Create($hGUI, $hTab) GUICtrlCreateTabItem("Apps") Local $x = 290 ; Right side fields container $g_AppFields = ObjCreate("Scripting.Dictionary") Local $fields = ["ButtonText", "RunFile", "RunAsAdmin", "WorkDir", "Arguments", "SingleInstance", "Sandboxie", "SandboxName", "Category", "Fave", "Hide", "SymLinkCreate"] For $i = 0 To UBound($fields) - 1 GUICtrlCreateLabel($fields[$i] & ":", $x, 60 + $i * 27, 70, 18) If StringInStr("RunAsAdmin SingleInstance Sandboxie SymLinkCreate Fave Hide", $fields[$i]) Then $g_AppFields($fields[$i]) = GUICtrlCreateCheckbox("", $x + 90, 56 + $i * 27, 18, 18) Else $g_AppFields($fields[$i]) = GUICtrlCreateInput("", $x + 90, 56 + $i * 27, 250, 18) EndIf Next ; Add Symlinks multiline edit field below regular fields Local $symlinkY = 60 + UBound($fields) * 27 GUICtrlCreateLabel("Symlinks:", $x, $symlinkY, 70, 18) $g_AppsSymlinksEdit = GUICtrlCreateEdit("", $x + 90, $symlinkY, 250, 130, BitOR($ES_MULTILINE, $ES_WANTRETURN)) $g_AppTreeView = GUICtrlCreateTreeView($listviewX, $listviewY, $x + 90, $guiH-155, BitOR($TVS_HASBUTTONS, $TVS_LINESATROOT, $TVS_SHOWSELALWAYS)) $g_IgnoreBtn = GUICtrlCreateButton("🚫", $x + 10, 440, $btnH, $btnH) GUICtrlSetTip($g_IgnoreBtn, "Add to Ignore List and Delete.") $g_SaveBtn = GUICtrlCreateButton("💾", $x + 40, 440, $btnH, $btnH) GUICtrlSetTip($g_SaveBtn, "Save before selecting items in Tree.") $g_RefreshBtn = GUICtrlCreateButton("🔄", $x + 70, 440, $btnH, $btnH) GUICtrlSetTip($g_RefreshBtn, "Reload GUI to update Tree") ; Create context menu for TreeView and delete item $g_AppTreeViewMenu = GUICtrlCreateContextMenu($g_AppTreeView) $g_AppMenuDeleteItem = GUICtrlCreateMenuItem("Delete", $g_AppTreeViewMenu) ; Disable all buttons on startup _AppTab_Buttons_Disable() _AppTab_LoadIniFilesAndApps() _AppTab_DisableFields() EndFunc Func _AppTab_LoadIniFilesAndApps() Global $g_AppSections $g_AppSections = ObjCreate("Scripting.Dictionary") $g_AppTreeItemToSection = ObjCreate("Scripting.Dictionary") $g_AppTreeItemToIni = ObjCreate("Scripting.Dictionary") $g_AppCategoryTreeItems = ObjCreate("Scripting.Dictionary") $g_IniFiles = _FileListToArray($g_CategoryIniDir, "*.ini", 1) If @error Or Not IsArray($g_IniFiles) Then Return ; Clear previous tree nodes GUICtrlDelete($g_AppTreeView) $g_AppTreeView = GUICtrlCreateTreeView($listviewX, $listviewY, 250, $guiH-155, BitOR($TVS_HASBUTTONS, $TVS_LINESATROOT, $TVS_SHOWSELALWAYS)) ; Re-create context menu after deletion $g_AppTreeViewMenu = GUICtrlCreateContextMenu($g_AppTreeView) $g_AppMenuDeleteItem = GUICtrlCreateMenuItem("Delete", $g_AppTreeViewMenu) Local $favourites = ObjCreate("Scripting.Dictionary") Local $categories = ObjCreate("Scripting.Dictionary") For $f = 1 To $g_IniFiles[0] Local $file = $g_IniFiles[$f] Local $fileLower = StringLower($file) If $fileLower = "settings.ini" Or $fileLower = "ignorelist.ini" Then ContinueLoop Local $iniFile = $g_CategoryIniDir & "\" & $file Local $sections = IniReadSectionNames($iniFile) If Not IsArray($sections) Then ContinueLoop For $i = 1 To $sections[0] Local $appName = $sections[$i] Local $category = IniRead($iniFile, $appName, "Category", "") If $category = "" Then $category = "Uncategorized" Local $hide = IniRead($iniFile, $appName, "Hide", "0") Local $fave = IniRead($iniFile, $appName, "Fave", "0") If $fave = "1" Then $favourites.Add($appName, $iniFile) EndIf If Not $categories.Exists($category) Then $categories.Add($category, ObjCreate("Scripting.Dictionary")) EndIf $categories.Item($category).Add($appName, $iniFile) Next Next ; Add Favourites node (alphabetical) If $favourites.Count > 0 Then Local $favNode = GUICtrlCreateTreeViewItem("Favourites", $g_AppTreeView) ; Collect and sort favourite app names Local $faveNames[0] For $appName In $favourites.Keys _ArrayAdd($faveNames, $appName) Next _ArraySort($faveNames) For $i = 0 To UBound($faveNames) - 1 Local $appName = $faveNames[$i] Local $iniFile = $favourites.Item($appName) Local $hide = IniRead($iniFile, $appName, "Hide", "0") Local $buttonText = IniRead($iniFile, $appName, "ButtonText", $appName) Local $label = $buttonText If $hide = "1" Then $label = "(H) " & $buttonText Local $appNode = GUICtrlCreateTreeViewItem($label, $favNode) If Not $g_AppSections.Exists($appName) Then $g_AppSections.Add($appName, $iniFile) Else $g_AppSections.Item($appName) = $iniFile ; Or update, or skip EndIf $g_AppTreeItemToSection.Add($appNode, $appName) $g_AppTreeItemToIni.Add($appNode, $iniFile) Next EndIf ; Add categories (alphabetical) Local $catNames[0] For $category In $categories.Keys _ArrayAdd($catNames, $category) Next _ArraySort($catNames) For $i = 0 To UBound($catNames) - 1 Local $category = $catNames[$i] Local $catNode = GUICtrlCreateTreeViewItem($category, $g_AppTreeView) $g_AppCategoryTreeItems.Add($catNode, $category) ; Collect and sort app names in this category Local $appNames[0] For $appName In $categories.Item($category).Keys _ArrayAdd($appNames, $appName) Next _ArraySort($appNames) For $j = 0 To UBound($appNames) - 1 Local $appName = $appNames[$j] Local $iniFile = $categories.Item($category).Item($appName) Local $hide = IniRead($iniFile, $appName, "Hide", "0") Local $fave = IniRead($iniFile, $appName, "Fave", "0") ; If Fave=1, already added above If $fave = "1" Then ContinueLoop Local $buttonText = IniRead($iniFile, $appName, "ButtonText", $appName) Local $label = $buttonText If $hide = "1" Then $label = "(H) " & $buttonText Local $appNode = GUICtrlCreateTreeViewItem($label, $catNode) If Not $g_AppSections.Exists($appName) Then $g_AppSections.Add($appName, $iniFile) Else $g_AppSections.Item($appName) = $iniFile ; Or update, or skip EndIf $g_AppTreeItemToSection.Add($appNode, $appName) $g_AppTreeItemToIni.Add($appNode, $iniFile) Next Next EndFunc ; Enable all buttons (Ignore, Save) Func _AppTab_Buttons_Enable() GUICtrlSetState($g_IgnoreBtn, $GUI_ENABLE) GUICtrlSetState($g_SaveBtn, $GUI_ENABLE) EndFunc ; Disable all buttons (Ignore, Save) Func _AppTab_Buttons_Disable() GUICtrlSetState($g_IgnoreBtn, $GUI_DISABLE) GUICtrlSetState($g_SaveBtn, $GUI_DISABLE) EndFunc Func Tab_App_HandleEvents($msg) ; Handle buttons and context menu Switch $msg Case $g_SaveBtn If $g_SelectedIni <> "" And $g_SelectedSection <> "" Then _AppTab_SaveFields($g_SelectedIni, $g_SelectedSection) ;~ _AppTab_LoadIniFilesAndApps() EndIf Case $g_IgnoreBtn _AppTab_IgnoreSelected() Case $g_RefreshBtn GUIDelete($hGUI) ShowSettingsGUI() Case $g_AppMenuDeleteItem _AppTab_DeleteSelected() Case $g_AppFields("SymLinkCreate") ; Enable/disable symlinks field based on checkbox If GUICtrlRead($g_AppFields("SymLinkCreate")) = $GUI_CHECKED Then GUICtrlSetState($g_AppsSymlinksEdit, $GUI_ENABLE) Else GUICtrlSetState($g_AppsSymlinksEdit, $GUI_DISABLE) EndIf Case $g_AppFields("Sandboxie") ; Enable/disable SandboxName field based on checkbox If GUICtrlRead($g_AppFields("Sandboxie")) = $GUI_CHECKED Then GUICtrlSetState($g_AppFields("SandboxName"), $GUI_ENABLE) Else GUICtrlSetState($g_AppFields("SandboxName"), $GUI_DISABLE) EndIf EndSwitch Local $selectedItem = GUICtrlRead($g_AppTreeView) ; Only act if the selection changed If $selectedItem <> $g_AppLastSelectedItem Then ; If a category node is selected If $selectedItem <> 0 And $g_AppCategoryTreeItems.Exists($selectedItem) Then _AppTab_ClearFields() _AppTab_DisableFields() GUICtrlSetState($g_SaveBtn, $GUI_DISABLE) GUICtrlSetState($g_IgnoreBtn, $GUI_DISABLE) $g_SelectedIni = "" $g_SelectedSection = "" ; If last selected was a valid app item and now whitespace/node: disable buttons ElseIf $g_AppLastSelectedItem <> 0 And $g_AppTreeItemToSection.Exists($g_AppLastSelectedItem) _ And ($selectedItem = 0 Or Not $g_AppTreeItemToSection.Exists($selectedItem)) Then _AppTab_ClearFields() _AppTab_Buttons_Disable() $g_SelectedIni = "" $g_SelectedSection = "" ; If selection changed to a valid app item: enable buttons ElseIf $selectedItem <> 0 And $g_AppTreeItemToSection.Exists($selectedItem) Then $g_SelectedSection = $g_AppTreeItemToSection.Item($selectedItem) $g_SelectedIni = $g_AppTreeItemToIni.Item($selectedItem) _AppTab_PopulateFields($g_SelectedIni, $g_SelectedSection) _AppTab_EnableFields() _AppTab_Buttons_Enable() ; If selection changed to whitespace/node, disable buttons Else _AppTab_ClearFields() _AppTab_Buttons_Disable() $g_SelectedIni = "" $g_SelectedSection = "" EndIf $g_AppLastSelectedItem = $selectedItem EndIf EndFunc Func _AppTab_PopulateFields($iniFile, $section) For $key In $g_AppFields.Keys() Local $val = IniRead($iniFile, $section, $key, "") If StringInStr("RunAsAdmin SingleInstance Sandboxie SymLinkCreate Fave Hide", $key) Then GUICtrlSetState($g_AppFields($key), ($val = "1") ? $GUI_CHECKED : $GUI_UNCHECKED) Else GUICtrlSetData($g_AppFields($key), $val) EndIf GUICtrlSetState($g_AppFields($key), $GUI_ENABLE) Next ; Populate symlinks multiline edit Local $symlinks = "" Local $idx = 1 While 1 Local $val = IniRead($iniFile, $section, "Symlink" & $idx, "") If $val = "" Then ExitLoop $symlinks &= $val & @CRLF $idx += 1 WEnd GUICtrlSetData($g_AppsSymlinksEdit, StringTrimRight($symlinks, 2)) ; Enable/disable symlinks field according to SymLinkCreate checkbox If GUICtrlRead($g_AppFields("SymLinkCreate")) = $GUI_CHECKED Then GUICtrlSetState($g_AppsSymlinksEdit, $GUI_ENABLE) Else GUICtrlSetState($g_AppsSymlinksEdit, $GUI_DISABLE) EndIf ; Enable/disable SandboxName field according to Sandboxie checkbox If GUICtrlRead($g_AppFields("Sandboxie")) = $GUI_CHECKED Then GUICtrlSetState($g_AppFields("SandboxName"), $GUI_ENABLE) Else GUICtrlSetState($g_AppFields("SandboxName"), $GUI_DISABLE) EndIf EndFunc Func _AppTab_SaveFields($iniFile, $section) For $key In $g_AppFields.Keys() If StringInStr("RunAsAdmin SingleInstance Sandboxie SymLinkCreate Fave Hide", $key) Then Local $v = (GUICtrlRead($g_AppFields($key)) = $GUI_CHECKED) ? "1" : "0" IniWrite($iniFile, $section, $key, $v) Else IniWrite($iniFile, $section, $key, GUICtrlRead($g_AppFields($key))) EndIf GUICtrlSetState($g_AppFields($key), $GUI_DISABLE) Next ; Save symlinks from multiline edit as Symlink1=..., Symlink2=..., ... Local $symlinksText = GUICtrlRead($g_AppsSymlinksEdit) Local $symlinksArr = StringSplit(StringStripCR($symlinksText), @LF) ; First, delete any old SymlinkX keys Local $idx = 1 While 1 Local $exists = IniRead($iniFile, $section, "Symlink" & $idx, "") If $exists = "" Then ExitLoop IniDelete($iniFile, $section, "Symlink" & $idx) $idx += 1 WEnd ; Write new symlinks If $symlinksArr[0] > 0 Then For $i = 1 To $symlinksArr[0] If StringStripWS($symlinksArr[$i], 3) <> "" Then IniWrite($iniFile, $section, "Symlink" & $i, $symlinksArr[$i]) EndIf Next EndIf GUICtrlSetState($g_AppsSymlinksEdit, $GUI_DISABLE) ; Disable SandboxName field after save GUICtrlSetState($g_AppFields("SandboxName"), $GUI_DISABLE) EndFunc Func _AppTab_ClearFields() For $key In $g_AppFields.Keys() If StringInStr("RunAsAdmin SingleInstance Sandboxie SymLinkCreate Fave Hide", $key) Then GUICtrlSetState($g_AppFields($key), $GUI_UNCHECKED) Else GUICtrlSetData($g_AppFields($key), "") EndIf GUICtrlSetState($g_AppFields($key), $GUI_ENABLE) Next GUICtrlSetData($g_AppsSymlinksEdit, "") ; Enable/disable Symlinks field according to SymLinkCreate checkbox If GUICtrlRead($g_AppFields("SymLinkCreate")) = $GUI_CHECKED Then GUICtrlSetState($g_AppsSymlinksEdit, $GUI_ENABLE) Else GUICtrlSetState($g_AppsSymlinksEdit, $GUI_DISABLE) EndIf ; Enable/disable SandboxName field according to Sandboxie checkbox If GUICtrlRead($g_AppFields("Sandboxie")) = $GUI_CHECKED Then GUICtrlSetState($g_AppFields("SandboxName"), $GUI_ENABLE) Else GUICtrlSetState($g_AppFields("SandboxName"), $GUI_DISABLE) EndIf EndFunc Func _AppTab_EnableFields() For $key In $g_AppFields.Keys() GUICtrlSetState($g_AppFields($key), $GUI_ENABLE) Next ; Enable/disable symlinks field according to SymLinkCreate If GUICtrlRead($g_AppFields("SymLinkCreate")) = $GUI_CHECKED Then GUICtrlSetState($g_AppsSymlinksEdit, $GUI_ENABLE) Else GUICtrlSetState($g_AppsSymlinksEdit, $GUI_DISABLE) EndIf ; Enable/disable SandboxName field according to Sandboxie checkbox If GUICtrlRead($g_AppFields("Sandboxie")) = $GUI_CHECKED Then GUICtrlSetState($g_AppFields("SandboxName"), $GUI_ENABLE) Else GUICtrlSetState($g_AppFields("SandboxName"), $GUI_DISABLE) EndIf EndFunc Func _AppTab_DisableFields() For $key In $g_AppFields.Keys() GUICtrlSetState($g_AppFields($key), $GUI_DISABLE) Next GUICtrlSetState($g_AppsSymlinksEdit, $GUI_DISABLE) GUICtrlSetState($g_AppFields("SandboxName"), $GUI_DISABLE) EndFunc Func _AppTab_DeleteSelected($skipConfirm = False) Local $selectedItem = GUICtrlRead($g_AppTreeView) If $selectedItem = 0 Then Return ; --- CATEGORY NODE DELETION --- If $g_AppCategoryTreeItems.Exists($selectedItem) Then Local $category = $g_AppCategoryTreeItems.Item($selectedItem) Local $iniFile = $g_CategoryIniDir & "\" & $category & ".ini" ; SAFEGUARD: Never delete Settings.ini or IgnoreList.ini If StringInStr(StringLower($iniFile), "settings.ini") Or StringInStr(StringLower($iniFile), "ignorelist.ini") Then Return If Not $skipConfirm Then Local $answer = MsgBox(1 + 32, "Delete Category", _ "Are you sure you want to delete the entire category '" & $category & "'?" & @CRLF & _ "This will remove the INI file (" & $category & ".ini) and all its apps." & @CRLF & _ "This cannot be undone.", 0) If $answer <> 1 Then Return EndIf If FileExists($iniFile) Then FileDelete($iniFile) GUICtrlDelete($selectedItem) $g_AppCategoryTreeItems.Remove($selectedItem) $g_SelectedIni = "" $g_SelectedSection = "" $g_AppLastSelectedItem = 0 _AppTab_ClearFields() _AppTab_Buttons_Disable() Return EndIf ; --- APP NODE DELETION --- If Not $g_AppTreeItemToSection.Exists($selectedItem) Then Return Local $appName = $g_AppTreeItemToSection.Item($selectedItem) Local $iniFile = $g_AppSections.Item($appName) ; SAFEGUARD: Never delete from Settings.ini If StringInStr(StringLower($iniFile), "settings.ini") Then Return If Not $skipConfirm Then Local $answer = MsgBox(1 + 32, "Delete App", "Are you sure you want to delete '" & $appName & "'?" & @CRLF & "This cannot be undone.", 0) If $answer <> 1 Then Return EndIf IniDelete($iniFile, $appName) GUICtrlDelete($selectedItem) $g_AppSections.Remove($appName) $g_AppTreeItemToSection.Remove($selectedItem) $g_AppTreeItemToIni.Remove($selectedItem) _AppTab_ClearFields() $g_SelectedIni = "" $g_SelectedSection = "" $g_AppLastSelectedItem = 0 _AppTab_Buttons_Disable() EndFunc Func _AppTab_IgnoreSelected() Local $selectedItem = GUICtrlRead($g_AppTreeView) If $selectedItem = 0 Or Not $g_AppTreeItemToSection.Exists($selectedItem) Then Return Local $appName = $g_AppTreeItemToSection.Item($selectedItem) Local $iniFile = $g_AppSections.Item($appName) ; SAFEGUARD: Never ignore from Settings.ini If StringInStr(StringLower($iniFile), "settings.ini") Then Return ; Get the RunFile (path) to ignore Local $ignorePath = IniRead($iniFile, $appName, "RunFile", "") If $ignorePath = "" Then Return ; --- Custom Ignore Confirmation --- Local $answer = MsgBox(1 + 32, "Ignore App", _ "Confirm adding '" & $appName & "' (" & $ignorePath & ") to the Ignore List and delete from App list." & @CRLF & _ @CRLF & _ "You can restore ignored apps via the Ignore tab.", 0) If $answer <> 1 Then Return ; Add the path to IgnoreList.ini if not already present Local $ignoreIni = @ScriptDir & "\App\IgnoreList.ini" Local $ignoreArr = FileReadToArray($ignoreIni) Local $exists = False If IsArray($ignoreArr) Then For $i = 0 To UBound($ignoreArr) - 1 If StringStripWS($ignoreArr[$i], 3) = $ignorePath Then $exists = True ExitLoop EndIf Next EndIf If Not $exists Then Local $hFile = FileOpen($ignoreIni, $FO_APPEND) If $hFile <> -1 Then FileWriteLine($hFile, $ignorePath) FileClose($hFile) EndIf EndIf ; Delete from Apps tab (calls delete logic) _AppTab_DeleteSelected(True) ; Update Ignore tab view GUICtrlSetState($g_IgnoreEdit, $GUI_ENABLE) _Ignore_EditPopulate() GUICtrlSetState($g_IgnoreEdit, $GUI_DISABLE) EndFunc Here's the after script: expandcollapse popup; Tab_Apps.au3 #include-once #include <GuiTreeView.au3> #include <File.au3> #include <Array.au3> Global $g_CategoryIniDir = @ScriptDir & "\App" Global $g_AppTreeView, $g_AppFields, $g_IniFiles, $g_AppSections, $g_SelectedIni, $g_SelectedSection Global $g_SaveBtn, $g_IgnoreBtn, $g_RefreshBtn Global $g_AppTreeItemToSection = ObjCreate("Scripting.Dictionary") Global $g_AppTreeItemToIni = ObjCreate("Scripting.Dictionary") Global $g_AppLastSelectedItem = 0 Global $guiW, $guiH, $listviewX, $listviewY, $btnW, $btnH, $footer_gap, $hGUI Global $g_AppCategoryTreeItems = ObjCreate("Scripting.Dictionary") Global $g_AppsSymlinksEdit Global Const $ES_MULTILINE = 0x0004 Global Const $ES_WANTRETURN = 0x1000 Global $g_AppTreeViewMenu, $g_AppMenuDeleteItem Func Tab_Apps_Create($hGUI, $hTab) GUICtrlCreateTabItem("Apps") Local $x = 290 ; Right side fields container $g_AppFields = ObjCreate("Scripting.Dictionary") Local $fields = ["ButtonText", "RunFile", "RunAsAdmin", "WorkDir", "Arguments", "SingleInstance", "Sandboxie", "SandboxName", "Category", "Fave", "Hide", "SymLinkCreate"] For $i = 0 To UBound($fields) - 1 GUICtrlCreateLabel($fields[$i] & ":", $x, 60 + $i * 27, 70, 18) If StringInStr("RunAsAdmin SingleInstance Sandboxie SymLinkCreate Fave Hide", $fields[$i]) Then $g_AppFields($fields[$i]) = GUICtrlCreateCheckbox("", $x + 90, 56 + $i * 27, 18, 18) Else $g_AppFields($fields[$i]) = GUICtrlCreateInput("", $x + 90, 56 + $i * 27, 250, 18) EndIf Next ; Add Symlinks multiline edit field below regular fields Local $symlinkY = 60 + UBound($fields) * 27 GUICtrlCreateLabel("Symlinks:", $x, $symlinkY, 70, 18) $g_AppsSymlinksEdit = GUICtrlCreateEdit("", $x + 90, $symlinkY, 250, 130, BitOR($ES_MULTILINE, $ES_WANTRETURN)) $g_AppTreeView = GUICtrlCreateTreeView($listviewX, $listviewY, $x + 90, $guiH-155, BitOR($TVS_HASBUTTONS, $TVS_LINESATROOT, $TVS_SHOWSELALWAYS)) $g_IgnoreBtn = GUICtrlCreateButton("🚫", $x + 10, 440, $btnH, $btnH) GUICtrlSetTip($g_IgnoreBtn, "Add to Ignore List and Delete.") $g_SaveBtn = GUICtrlCreateButton("💾", $x + 40, 440, $btnH, $btnH) GUICtrlSetTip($g_SaveBtn, "Save before selecting items in Tree.") $g_RefreshBtn = GUICtrlCreateButton("🔄", $x + 70, 440, $btnH, $btnH) GUICtrlSetTip($g_RefreshBtn, "Reload GUI to update Tree") ; Create context menu for TreeView and delete item $g_AppTreeViewMenu = GUICtrlCreateContextMenu($g_AppTreeView) $g_AppMenuDeleteItem = GUICtrlCreateMenuItem("Delete", $g_AppTreeViewMenu) ; Disable all buttons on startup GUIRegisterMsg($WM_NOTIFY, Tab_Apps_WM_NOTIFY) _AppTab_Buttons_Disable() _AppTab_LoadIniFilesAndApps() _AppTab_DisableFields() EndFunc Func _AppTab_LoadIniFilesAndApps() Global $g_AppSections $g_AppSections = ObjCreate("Scripting.Dictionary") $g_AppTreeItemToSection = ObjCreate("Scripting.Dictionary") $g_AppTreeItemToIni = ObjCreate("Scripting.Dictionary") $g_AppCategoryTreeItems = ObjCreate("Scripting.Dictionary") $g_IniFiles = _FileListToArray($g_CategoryIniDir, "*.ini", 1) If @error Or Not IsArray($g_IniFiles) Then Return ; Clear previous tree nodes GUICtrlDelete($g_AppTreeView) $g_AppTreeView = GUICtrlCreateTreeView($listviewX, $listviewY, 250, $guiH-155, BitOR($TVS_HASBUTTONS, $TVS_LINESATROOT, $TVS_SHOWSELALWAYS)) ; Re-create context menu after deletion $g_AppTreeViewMenu = GUICtrlCreateContextMenu($g_AppTreeView) $g_AppMenuDeleteItem = GUICtrlCreateMenuItem("Delete", $g_AppTreeViewMenu) Local $favourites = ObjCreate("Scripting.Dictionary") Local $categories = ObjCreate("Scripting.Dictionary") For $f = 1 To $g_IniFiles[0] Local $file = $g_IniFiles[$f] Local $fileLower = StringLower($file) If $fileLower = "settings.ini" Or $fileLower = "ignorelist.ini" Then ContinueLoop Local $iniFile = $g_CategoryIniDir & "\" & $file Local $sections = IniReadSectionNames($iniFile) If Not IsArray($sections) Then ContinueLoop For $i = 1 To $sections[0] Local $appName = $sections[$i] Local $category = IniRead($iniFile, $appName, "Category", "") If $category = "" Then $category = "Uncategorized" Local $hide = IniRead($iniFile, $appName, "Hide", "0") Local $fave = IniRead($iniFile, $appName, "Fave", "0") If $fave = "1" Then $favourites.Add($appName, $iniFile) EndIf If Not $categories.Exists($category) Then $categories.Add($category, ObjCreate("Scripting.Dictionary")) EndIf $categories.Item($category).Add($appName, $iniFile) Next Next ; Add Favourites node (alphabetical) If $favourites.Count > 0 Then Local $favNode = GUICtrlCreateTreeViewItem("Favourites", $g_AppTreeView) ; Collect and sort favourite app names Local $faveNames[0] For $appName In $favourites.Keys _ArrayAdd($faveNames, $appName) Next _ArraySort($faveNames) For $i = 0 To UBound($faveNames) - 1 Local $appName = $faveNames[$i] Local $iniFile = $favourites.Item($appName) Local $hide = IniRead($iniFile, $appName, "Hide", "0") Local $buttonText = IniRead($iniFile, $appName, "ButtonText", $appName) Local $label = $buttonText If $hide = "1" Then $label = "(H) " & $buttonText Local $appNode = GUICtrlCreateTreeViewItem($label, $favNode) If Not $g_AppSections.Exists($appName) Then $g_AppSections.Add($appName, $iniFile) Else $g_AppSections.Item($appName) = $iniFile ; Or update, or skip EndIf $g_AppTreeItemToSection.Add($appNode, $appName) $g_AppTreeItemToIni.Add($appNode, $iniFile) Next EndIf ; Add categories (alphabetical) Local $catNames[0] For $category In $categories.Keys _ArrayAdd($catNames, $category) Next _ArraySort($catNames) For $i = 0 To UBound($catNames) - 1 Local $category = $catNames[$i] Local $catNode = GUICtrlCreateTreeViewItem($category, $g_AppTreeView) $g_AppCategoryTreeItems.Add($catNode, $category) ; Collect and sort app names in this category Local $appNames[0] For $appName In $categories.Item($category).Keys _ArrayAdd($appNames, $appName) Next _ArraySort($appNames) For $j = 0 To UBound($appNames) - 1 Local $appName = $appNames[$j] Local $iniFile = $categories.Item($category).Item($appName) Local $hide = IniRead($iniFile, $appName, "Hide", "0") Local $fave = IniRead($iniFile, $appName, "Fave", "0") ; If Fave=1, already added above If $fave = "1" Then ContinueLoop Local $buttonText = IniRead($iniFile, $appName, "ButtonText", $appName) Local $label = $buttonText If $hide = "1" Then $label = "(H) " & $buttonText Local $appNode = GUICtrlCreateTreeViewItem($label, $catNode) If Not $g_AppSections.Exists($appName) Then $g_AppSections.Add($appName, $iniFile) Else $g_AppSections.Item($appName) = $iniFile ; Or update, or skip EndIf $g_AppTreeItemToSection.Add($appNode, $appName) $g_AppTreeItemToIni.Add($appNode, $iniFile) Next Next EndFunc ; Enable all buttons (Ignore, Save) Func _AppTab_Buttons_Enable() GUICtrlSetState($g_IgnoreBtn, $GUI_ENABLE) GUICtrlSetState($g_SaveBtn, $GUI_ENABLE) EndFunc ; Disable all buttons (Ignore, Save) Func _AppTab_Buttons_Disable() GUICtrlSetState($g_IgnoreBtn, $GUI_DISABLE) GUICtrlSetState($g_SaveBtn, $GUI_DISABLE) EndFunc Func Tab_App_HandleEvents($msg) ; Handle buttons and context menu Switch $msg Case $g_SaveBtn If $g_SelectedIni <> "" And $g_SelectedSection <> "" Then _AppTab_SaveFields($g_SelectedIni, $g_SelectedSection) ;~ _AppTab_LoadIniFilesAndApps() EndIf Case $g_IgnoreBtn _AppTab_IgnoreSelected() Case $g_RefreshBtn GUIDelete($hGUI) ShowSettingsGUI() Case $g_AppMenuDeleteItem _AppTab_DeleteSelected() Case $g_AppFields("SymLinkCreate") ; Enable/disable symlinks field based on checkbox If GUICtrlRead($g_AppFields("SymLinkCreate")) = $GUI_CHECKED Then GUICtrlSetState($g_AppsSymlinksEdit, $GUI_ENABLE) Else GUICtrlSetState($g_AppsSymlinksEdit, $GUI_DISABLE) EndIf Case $g_AppFields("Sandboxie") ; Enable/disable SandboxName field based on checkbox If GUICtrlRead($g_AppFields("Sandboxie")) = $GUI_CHECKED Then GUICtrlSetState($g_AppFields("SandboxName"), $GUI_ENABLE) Else GUICtrlSetState($g_AppFields("SandboxName"), $GUI_DISABLE) EndIf EndSwitch Local $selectedItem = GUICtrlRead($g_AppTreeView) ; Only act if the selection changed If $selectedItem <> $g_AppLastSelectedItem Then ; If a category node is selected If $selectedItem <> 0 And $g_AppCategoryTreeItems.Exists($selectedItem) Then _AppTab_ClearFields() _AppTab_DisableFields() GUICtrlSetState($g_SaveBtn, $GUI_DISABLE) GUICtrlSetState($g_IgnoreBtn, $GUI_DISABLE) $g_SelectedIni = "" $g_SelectedSection = "" ; If last selected was a valid app item and now whitespace/node: disable buttons ElseIf $g_AppLastSelectedItem <> 0 And $g_AppTreeItemToSection.Exists($g_AppLastSelectedItem) _ And ($selectedItem = 0 Or Not $g_AppTreeItemToSection.Exists($selectedItem)) Then _AppTab_ClearFields() _AppTab_Buttons_Disable() $g_SelectedIni = "" $g_SelectedSection = "" ; If selection changed to a valid app item: enable buttons ElseIf $selectedItem <> 0 And $g_AppTreeItemToSection.Exists($selectedItem) Then $g_SelectedSection = $g_AppTreeItemToSection.Item($selectedItem) $g_SelectedIni = $g_AppTreeItemToIni.Item($selectedItem) _AppTab_PopulateFields($g_SelectedIni, $g_SelectedSection) _AppTab_EnableFields() _AppTab_Buttons_Enable() ; If selection changed to whitespace/node, disable buttons Else _AppTab_ClearFields() _AppTab_Buttons_Disable() $g_SelectedIni = "" $g_SelectedSection = "" EndIf $g_AppLastSelectedItem = $selectedItem EndIf EndFunc Func _AppTab_PopulateFields($iniFile, $section) For $key In $g_AppFields.Keys() Local $val = IniRead($iniFile, $section, $key, "") If StringInStr("RunAsAdmin SingleInstance Sandboxie SymLinkCreate Fave Hide", $key) Then GUICtrlSetState($g_AppFields($key), ($val = "1") ? $GUI_CHECKED : $GUI_UNCHECKED) Else GUICtrlSetData($g_AppFields($key), $val) EndIf GUICtrlSetState($g_AppFields($key), $GUI_ENABLE) Next ; Populate symlinks multiline edit Local $symlinks = "" Local $idx = 1 While 1 Local $val = IniRead($iniFile, $section, "Symlink" & $idx, "") If $val = "" Then ExitLoop $symlinks &= $val & @CRLF $idx += 1 WEnd GUICtrlSetData($g_AppsSymlinksEdit, StringTrimRight($symlinks, 2)) ; Enable/disable symlinks field according to SymLinkCreate checkbox If GUICtrlRead($g_AppFields("SymLinkCreate")) = $GUI_CHECKED Then GUICtrlSetState($g_AppsSymlinksEdit, $GUI_ENABLE) Else GUICtrlSetState($g_AppsSymlinksEdit, $GUI_DISABLE) EndIf ; Enable/disable SandboxName field according to Sandboxie checkbox If GUICtrlRead($g_AppFields("Sandboxie")) = $GUI_CHECKED Then GUICtrlSetState($g_AppFields("SandboxName"), $GUI_ENABLE) Else GUICtrlSetState($g_AppFields("SandboxName"), $GUI_DISABLE) EndIf EndFunc Func _AppTab_SaveFields($iniFile, $section) For $key In $g_AppFields.Keys() If StringInStr("RunAsAdmin SingleInstance Sandboxie SymLinkCreate Fave Hide", $key) Then Local $v = (GUICtrlRead($g_AppFields($key)) = $GUI_CHECKED) ? "1" : "0" IniWrite($iniFile, $section, $key, $v) Else IniWrite($iniFile, $section, $key, GUICtrlRead($g_AppFields($key))) EndIf GUICtrlSetState($g_AppFields($key), $GUI_DISABLE) Next ; Save symlinks from multiline edit as Symlink1=..., Symlink2=..., ... Local $symlinksText = GUICtrlRead($g_AppsSymlinksEdit) Local $symlinksArr = StringSplit(StringStripCR($symlinksText), @LF) ; First, delete any old SymlinkX keys Local $idx = 1 While 1 Local $exists = IniRead($iniFile, $section, "Symlink" & $idx, "") If $exists = "" Then ExitLoop IniDelete($iniFile, $section, "Symlink" & $idx) $idx += 1 WEnd ; Write new symlinks If $symlinksArr[0] > 0 Then For $i = 1 To $symlinksArr[0] If StringStripWS($symlinksArr[$i], 3) <> "" Then IniWrite($iniFile, $section, "Symlink" & $i, $symlinksArr[$i]) EndIf Next EndIf GUICtrlSetState($g_AppsSymlinksEdit, $GUI_DISABLE) ; Disable SandboxName field after save GUICtrlSetState($g_AppFields("SandboxName"), $GUI_DISABLE) EndFunc Func _AppTab_ClearFields() For $key In $g_AppFields.Keys() If StringInStr("RunAsAdmin SingleInstance Sandboxie SymLinkCreate Fave Hide", $key) Then GUICtrlSetState($g_AppFields($key), $GUI_UNCHECKED) Else GUICtrlSetData($g_AppFields($key), "") EndIf GUICtrlSetState($g_AppFields($key), $GUI_ENABLE) Next GUICtrlSetData($g_AppsSymlinksEdit, "") ; Enable/disable Symlinks field according to SymLinkCreate checkbox If GUICtrlRead($g_AppFields("SymLinkCreate")) = $GUI_CHECKED Then GUICtrlSetState($g_AppsSymlinksEdit, $GUI_ENABLE) Else GUICtrlSetState($g_AppsSymlinksEdit, $GUI_DISABLE) EndIf ; Enable/disable SandboxName field according to Sandboxie checkbox If GUICtrlRead($g_AppFields("Sandboxie")) = $GUI_CHECKED Then GUICtrlSetState($g_AppFields("SandboxName"), $GUI_ENABLE) Else GUICtrlSetState($g_AppFields("SandboxName"), $GUI_DISABLE) EndIf EndFunc Func _AppTab_EnableFields() For $key In $g_AppFields.Keys() GUICtrlSetState($g_AppFields($key), $GUI_ENABLE) Next ; Enable/disable symlinks field according to SymLinkCreate If GUICtrlRead($g_AppFields("SymLinkCreate")) = $GUI_CHECKED Then GUICtrlSetState($g_AppsSymlinksEdit, $GUI_ENABLE) Else GUICtrlSetState($g_AppsSymlinksEdit, $GUI_DISABLE) EndIf ; Enable/disable SandboxName field according to Sandboxie checkbox If GUICtrlRead($g_AppFields("Sandboxie")) = $GUI_CHECKED Then GUICtrlSetState($g_AppFields("SandboxName"), $GUI_ENABLE) Else GUICtrlSetState($g_AppFields("SandboxName"), $GUI_DISABLE) EndIf EndFunc Func _AppTab_DisableFields() For $key In $g_AppFields.Keys() GUICtrlSetState($g_AppFields($key), $GUI_DISABLE) Next GUICtrlSetState($g_AppsSymlinksEdit, $GUI_DISABLE) GUICtrlSetState($g_AppFields("SandboxName"), $GUI_DISABLE) EndFunc Func _AppTab_DeleteSelected($skipConfirm = False) Local $selectedItem = GUICtrlRead($g_AppTreeView) If $selectedItem = 0 Then Return ; --- CATEGORY NODE DELETION --- If $g_AppCategoryTreeItems.Exists($selectedItem) Then Local $category = $g_AppCategoryTreeItems.Item($selectedItem) Local $iniFile = $g_CategoryIniDir & "\" & $category & ".ini" ; SAFEGUARD: Never delete Settings.ini or IgnoreList.ini If StringInStr(StringLower($iniFile), "settings.ini") Or StringInStr(StringLower($iniFile), "ignorelist.ini") Then Return If Not $skipConfirm Then Local $answer = MsgBox(1 + 32, "Delete Category", _ "Are you sure you want to delete the entire category '" & $category & "'?" & @CRLF & _ "This will remove the INI file (" & $category & ".ini) and all its apps." & @CRLF & _ "This cannot be undone.", 0) If $answer <> 1 Then Return EndIf If FileExists($iniFile) Then FileDelete($iniFile) GUICtrlDelete($selectedItem) $g_AppCategoryTreeItems.Remove($selectedItem) $g_SelectedIni = "" $g_SelectedSection = "" $g_AppLastSelectedItem = 0 _AppTab_ClearFields() _AppTab_Buttons_Disable() Return EndIf ; --- APP NODE DELETION --- If Not $g_AppTreeItemToSection.Exists($selectedItem) Then Return Local $appName = $g_AppTreeItemToSection.Item($selectedItem) Local $iniFile = $g_AppSections.Item($appName) ; SAFEGUARD: Never delete from Settings.ini If StringInStr(StringLower($iniFile), "settings.ini") Then Return If Not $skipConfirm Then Local $answer = MsgBox(1 + 32, "Delete App", "Are you sure you want to delete '" & $appName & "'?" & @CRLF & "This cannot be undone.", 0) If $answer <> 1 Then Return EndIf IniDelete($iniFile, $appName) GUICtrlDelete($selectedItem) $g_AppSections.Remove($appName) $g_AppTreeItemToSection.Remove($selectedItem) $g_AppTreeItemToIni.Remove($selectedItem) _AppTab_ClearFields() $g_SelectedIni = "" $g_SelectedSection = "" $g_AppLastSelectedItem = 0 _AppTab_Buttons_Disable() EndFunc Func _AppTab_IgnoreSelected() Local $selectedItem = GUICtrlRead($g_AppTreeView) If $selectedItem = 0 Or Not $g_AppTreeItemToSection.Exists($selectedItem) Then Return Local $appName = $g_AppTreeItemToSection.Item($selectedItem) Local $iniFile = $g_AppSections.Item($appName) ; SAFEGUARD: Never ignore from Settings.ini If StringInStr(StringLower($iniFile), "settings.ini") Then Return ; Get the RunFile (path) to ignore Local $ignorePath = IniRead($iniFile, $appName, "RunFile", "") If $ignorePath = "" Then Return ; --- Custom Ignore Confirmation --- Local $answer = MsgBox(1 + 32, "Ignore App", _ "Confirm adding '" & $appName & "' (" & $ignorePath & ") to the Ignore List and delete from App list." & @CRLF & _ @CRLF & _ "You can restore ignored apps via the Ignore tab.", 0) If $answer <> 1 Then Return ; Add the path to IgnoreList.ini if not already present Local $ignoreIni = @ScriptDir & "\App\IgnoreList.ini" Local $ignoreArr = FileReadToArray($ignoreIni) Local $exists = False If IsArray($ignoreArr) Then For $i = 0 To UBound($ignoreArr) - 1 If StringStripWS($ignoreArr[$i], 3) = $ignorePath Then $exists = True ExitLoop EndIf Next EndIf If Not $exists Then Local $hFile = FileOpen($ignoreIni, $FO_APPEND) If $hFile <> -1 Then FileWriteLine($hFile, $ignorePath) FileClose($hFile) EndIf EndIf ; Delete from Apps tab (calls delete logic) _AppTab_DeleteSelected(True) ; Update Ignore tab view GUICtrlSetState($g_IgnoreEdit, $GUI_ENABLE) _Ignore_EditPopulate() GUICtrlSetState($g_IgnoreEdit, $GUI_DISABLE) EndFunc Func Tab_Apps_WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam) If $tNMHDR.idFrom <> $g_AppTreeView Then Return $GUI_RUNDEFMSG If $tNMHDR.code <> $NM_RCLICK Then Return $GUI_RUNDEFMSG ; Find which item was right-clicked Local $cursor = GUIGetCursorInfo($hWnd) Local $ctrlPos = ControlGetPos($hWnd, "", $tNMHDR.idFrom) Local $relX = $cursor[0] - $ctrlPos[0] Local $relY = $cursor[1] - $ctrlPos[1] Local $itemID = _GUICtrlTreeView_HitTestItem($wParam, $relX, $relY) If Not $itemID Then Return 1 ; block menu if nothing ; Select the item (this is all you need) _GUICtrlTreeView_SelectItem($wParam, $itemID) ; DO NOT call any event handler here Return $GUI_RUNDEFMSG EndFunc Any idea what I am doing wrong? Basically, the premise is that there is a treeview on the left hand side of the gui, clicking items inside the categories populates the fields and checkboxes on the right. Which is working as intended. But I am wanting the right click to move the selection to the mouse position just as your test script does. So in plain terms, your test script: 1. Left click to select node 1, item selected. 2. Right click node 3 to select and show right click context menu. 3. Select Delete, node 3 is deleted. But I can't get that behaviour in my own script! This is what is happening in mine: 1. Left click to select node 1, item selected. Correct. 2. Right click node 3 to select and show right click context menu. Correct. 3. Select Delete, node 1 is deleted. Incorrect Thanks for your help.
sl23 Posted September 16 Author Posted September 16 It's ok, its sorted! It was a mismatch between tree names and app names! Nine 1
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now