Skip to content

Nich-Cebolla/AutoHotkey-TreeViewEx

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

70 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AutoHotkey-TreeViewEx

A completely custom tree-view control for AutoHotkey (AHK).

Table of contents

  1. Introduction
    1. Use cases
    2. Getting started
    3. Dependencies
    4. Related libraries
    5. Examples
      1. Demo
      2. Context menu
  2. TreeViewEx_Tab.ahk
  3. TreeViewEx_ContextMenu.ahk
  4. TreeViewEx: Tested methods and properties
    1. TreeViewEx: Static methods
    2. TreeViewEx: Instance methods
    3. TreeViewEx: Instance properties
  5. TreeViewEx - Tested notification handlers
    1. TreeViewEx - Tested notification handlers - Node
    2. TreeViewEx - Tested notification handlers - Node_C
    3. TreeViewEx - Tested notification handlers - Node_Ptr
  6. TreeViewEx_Node
    1. Extending TreeViewEx_Node
    2. TVN_GETDISPINFO
    3. TVN_SETDISPINFO
    4. TreeViewEx_Node: Tested methods and properties
      1. TreeViewEx_Node: Static methods
      2. TreeViewEx_Node: Instance methods
      3. TreeViewEx_Node: Instance properties

Introduction

With over 30 classes, over 250 methods, and over 60 functions, TreeViewEx implements nearly all functionality related to tree-view controls offered by the Windows API.

TreeViewEx does not extend Gui.TreeView, nor does it inherit from Gui.Control. It is a completely custom class built from the ground up to provide the developer with a familiar AHK wrapper around one of Microsoft's most complex Win32 common controls.

Use cases

You can use TreeViewEx as a standard tree-view control, taking advantage of its many helpful tools and customization options:

  • Provides AHK wrappers for almost all of the TVM messages
  • Exposes all dynamic attributes to external code, including window styles, extended window styles, line / text color, state icons, and more
  • Includes custom functions to handle complex tasks such as recursive processing, sending and handling TVN notifications, defining window message handlers, etc...
  • Maps structure byte offsets to object properties so you can quickly fill in structure members using convenient property notation (no NumGet / NumPut needed)

The library's scope goes beyond that of just a tree-view control. TreeViewEx exposes the lower-level processes that AHK hides from our top-level code. Your code has direct access to the window messages and notifications sent to both the parent gui window and the tree-view control itself. These tools are packaged into familiar "OnCommand", "OnNotify", and "OnMessage" functions so you can seamlessly bridge old code with this advanced functionality.

Along with TreeViewEx is TreeViewEx_Node, an object-oriented approach to working with tree-view items that will feel more familiar and comfortable for those who have not explored Windows API concepts such as window messages and notifications. TreeViewEx_Node is an extensible framework for systematically controlling the content and presentation of the tree-view items. TreeViewEx_Node makes it easy for our AHK code to respond to all of the tree-view notifications like TVN_GETDISPINFO and NM_CLICK.

Check back regularly because I will soon be releasing code that subclasses TreeViewEx to:

  • Explore objects visually by recursively mapping object properties to tree-view items
  • Integrate with UIA to view a window's entire UIA tree
  • Inspect UIA element properties and available patterns

Getting started

To use the library #include VENV.ahk. VENV.ahk packages all of the files together. To make the library available to any script, I recommend this setup:

  • Clone the repository.
    git clone https://github.com/Nich-Cebolla/AutoHotkey-TreeViewEx
  • Make a copy of the cloned repository and work with the copy. This is to avoid a situation where pulling an update breaks our scripts; by using a separate copy we can give ourselves time to review updates before updating the active copy.
    xcopy AutoHotkey-TreeViewEx AutoHotkey-TreeViewEx-Active /I /E
  • Add a file TreeViewEx.ahk to your lib folder. In the file is a single statement.
    #include C:\users\you\path\to\AutoHotkey-TreeViewEx-Active\src\VENV.ahk

With this setup, we can use #include <TreeViewEx> from any other script. Also, when we want to test updates to the repository, we just need to go into that file and change the path to the VENV.ahk file in the git clone, then run our scripts that use TreeViewEx to check for errors. Then change the path back when done.

Dependencies

TreeViewEx requires the following dependencies. I recommend preparing the dependencies with a similar approach to the above steps.

  • Rect
    • Clone AutoHotkey-LibV2, create a copy of the directory to use as your active copy, then create a file Rect.ahk in your lib folder with #include C:\users\you\path\to\AutoHotkey-LibV2-Active\structs\Rect.ahk.
  • LibraryManager
    • LibraryManager is also in AutoHotkey-LibV2, so just create a file LibraryManager.ahk in your lib folder with #include C:\users\you\path\to\AutoHotkey-LibV2-Active\LibraryManager.ahk.
  • Container
    • Clone Container, create a copy of the directory to use as your active copy, then create a file Container.ahk in your lib folder with #include C:\users\you\path\to\Container-Active\src\Container.ahk.

Related libraries

  • ImageList: Create an ImageList from an array of file paths or an array of bitmap pointers. For use with TreeViewEx.Prototype.SetImageList and related methods. Requires several dependencies from the same repository.
  • Logfont: A full-featured font object. TreeViewEx has a built-in TreeViewEx_LogFont class which encapsulates the core functionality necessary for adjusting the control's font, but TreeViewEx_LogFont does not include functionality related to enumerating a system's fonts and evaluating the fonts. If your application would benefit from being able to find the optimal font available on the system, check out Logfont.
  • MenuEx: - A class that streamlines the process of creating a context menu. See file test\demo-context-menu.ahk for an example.

Examples

Demo

See the demo script test\demo-NotificationHandlers for a working example. The demo file will run as-is (but still requires the above dependencies). The demo script focuses on setting event handlers for TVN notifications. All nodes are added to the tree-view with item.pszText = LPSTR_TEXTCALLBACK and item.cChildren = TVIF_CHILDREN. The following notifications are handled in the demo:

Context menu

See test\demo-context-menu.ahk for an example of using TreeViewEx_ContextMenu

TreeViewEx_Tab.ahk

TreeViewEx_Tab.ahk is a separate script (not included in VENV.ahk) containing class TreeViewEx_Tab. TreeViewEx_Tab has one dependency, TabEx.ahk. TreeViewEx_Tab creates a tab control in a gui window and makes it easy to associate new TreeViewEx controls with an individual tab so the user can change what information is displayed by selecting a new tab.

For the developer, TreeViewEx_Tab handles all of the legwork around adding, positioning, displaying, and removing TreeViewEx controls and the tabs they are associated with. These are the general steps for using the class:

  1. Prepare TabEx.ahk in the same way as described above.
  2. Add a file TreeViewEx_Tab.ahk to your lib folder. In the file is a single statement.
    #include C:\users\you\path\to\AutoHotkey-TreeViewEx-Active\src\TreeViewEx_Tab.ahk
  3. In your script that will use TreeViewEx_Tab, include:
    #include <TreeViewEx_Tab>
  4. (Optional) Create a context menu class using MenuEx.
  5. (Optional) Define a function that all new TreeViewEx controls will be passed to to use custom instantiation logic.
  6. Define 0-3 options objects, each associated with a parameter of TreeViewEx_Tab.Prototype.__New.
    __New(GuiObj, Options?, DefaultAddOptions := '', DefaultTreeViewExOptions := '')
    None of the options are strictly necessary, but generally you'll want to create the Options object to specify the tab control's options, and optionally supply the objects described by steps 4 and 5 above. The other two, DefaultAddOptions and DefaultTreeViewExOptions, can be left the default for general use.
    • Options - The options for TreeViewEx_Tab and the tab control it will create. These are described in the parameter hint above TreeViewEx_Tab.Prototype.__New.
    • DefaultAddOptions - The default options that will be used when adding a TreeViewEx control via TreeViewEx_Tab.Prototype.Add. These are described in the parameter hint above TreeViewEx_Tab.Prototype.Add.
    • DefaultTreeViewExOptions - The default options that will be used when adding a TreeViewEx control via TreeViewEx_Tab.Prototype.Add. These are described in the parameter hint above TreeViewEx.Prototype.__New.
  7. Create the object
    options := { opt: 'w400 r15', name: 'tab' } ; no context menu or instantiation callback seen here
    tvexTab := TreeViewEx_Tab(GuiObj, options) ; assume GuiObj reference a Gui object
  8. Add TreeViewEx controls to the tab control by supplying a name. If using the default add options, calling TreeViewEx_Tab.Prototype.Add with just a name will:
  • Create a new tab using the name.
  • Create a new TreeViewEx control positioned neatly in the center of the tab control's client area. The control is associated with the newly created tab. This does not automatically display the tab (unless its the first tab).
  • Return a TreeViewEx_Tab.Item object. The TreeViewEx control is set to property "tvex".

See the test file test\test-TreeViewEx_Tab.ahk for a working demo.

TreeViewEx_ContextMenu.ahk

TreeViewEx_ContextMenu.ahk is a separate script (not included in VENV.ahk) containing class TreeViewEx_ContextMenu. TreeViewEx_ContextMenu extends MenuEx, which is required to use TreeViewEx_ContextMenu.

TreeViewEx_ContextMenu currently includes the following context menu items:

  • Copy node ID: Copies the handle of the item beneath the cursor.
  • Copy label: Copies the label of the item beneath the cursor.
  • Collapse recursive: Calls TreeViewEx.Prototype.CollapseRecursiveNotify for the item beneath the cursor.
  • Collapse all recursive: Calls TreeViewEx.Prototype.CollapseRecursiveNotify for all root items.
  • Collapse parent: Calls TreeViewEx.Prototype.CollapseNotify for the parent of the item beneath the cursor.
  • Collapse parent recursive: Calls TreeViewEx.Prototype.CollapseRecursiveNotify for the parent of the item beneath the cursor.
  • Collapse siblings: Calls TreeViewEx.Prototype.CollapseNotify for each sibling of the item beneath the cursor.
  • Collapse siblings recursive: Calls TreeViewEx.Prototype.CollapseRecursiveNotify for each sibling of the item beneath the cursor.
  • Expand recursive: Calls TreeViewEx.Prototype.ExpandRecursiveNotify for the item beneath the cursor.
  • Expand all recursive: Calls TreeViewEx.Prototype.ExpandRecursiveNotify for all root items.
  • Scroll to top: Sends TVM_ENSUREVISIBLE for the item identified by TVGN_ROOT.
  • Scroll to bottom: Sends TVM_ENSUREVISIBLE for the item identified by TVGN_LASTVISIBLE.
  • Select parent: Selects and sends TVM_ENSUREVISIBLE for the parent of the item beneath the cursor.
  • Select previous sibling: Selects and sends TVM_ENSUREVISIBLE for the sibling above the item beneath the cursor.
  • Select next sibling: Selects and sends TVM_ENSUREVISIBLE for the sibling beneath the item beneath the cursor.

TreeViewEx: Tested methods and properties

The following is a list of methods and properties. The items with an "X" next to them have been tested. The items with no "X" have not been tested. Most of the methods and properties probably work, but only the marked items have been verified.

TreeViewEx: Static methods

Name Is Tested
Add X
Delete X
Get X

TreeViewEx: Instance methods

Name Is Tested
__New X
AddNode X
AddNode_C
AddObj X
AddObjList X
AddObjListFromTemplate X
AddTemplate X
Collapse X
CollapseNotify X
CollapseRecursive X
CollapseRecursiveNotify X
CollapseReset
CollapseResetNotify
CopyText X
CreateDragImage
CreateParentSubclass X
DeleteAll X
DeleteAll_C X
DeleteChildren X
DeleteCommandCode X
DeleteItem X
DeleteMessageCode X
DeleteNode_C
DeleteNotifyCode X
Destroy X
Dispose X
EditLabel X
EndEditLabel X
EnsureVisible X
EnumChildren X
EnumChildrenRecursive X
Expand X
ExpandNotify X
ExpandPartial
ExpandRecursive X
ExpandRecursiveNotify X
ExpandRecursiveNotifySelective X
ExpandRecursiveSelective X
GetAdjacentRect X
GetBkColor X
GetChild X
GetCount X
GetEditControl X
GetExtendedStyle X
GetFont X
GetImageList
GetIndent
GetInsertMarkColor
GetISearchString
GetItem X
GetItemHeight X
GetItemRect X
GetItemState X
GetLineColor
GetLineRect
GetNext X
GetNode X
GetNode_C X
GetNode_Ptr X
GetParent X
GetPos X
GetRect X
GetRoot
GetScrollTime
GetSelected X
GetTemplate X
GetTemplateDispInfo
GetTemplateInfoTip
GetTemplateItemChange
GetTemplateKeyDown
GetTemplateNmtv X
GetText X
GetTextColor
GetTooltips
GetVisibleCount
HasChildren X
Hide X
HitTest X
Insert X
IsAncestor X
IsExpanded X
IsRoot X
MapAccIdToHTreeItem
MapHTreeItemToAccId
OnCommand
OnMessage X
OnNotify X
Redraw X
RemoveParentSubclass X
ScrollToBottom X
ScrollToTop X
Select X
SendBeginDrag
SendBeginLabelEdit X
SendBeginRDrag
SendDeleteItem
SendEndLabelEdit X
SendGetDispInfo
SendGetInfoTip
SendItemChanged
SendItemChanging
SendItemExpanded X
SendItemExpanding X
SendKeyDown
SendSetDispInfo
SetAutoScrollInfo
SetBkColor
SetContextMenu X
SetExtendedStyle
SetHeight X
SetImageList
SetIndent
SetInsertMark
SetInsertMarkColor
SetItem X
SetItemHeight
SetItemState X
SetLineColor
SetNodeConstructor X
SetRedraw X
SetScrollTime
SetStatus X
SetTextColor
SetTooltips
SetTvexTabId X
Show X
ShowInfoTip
SortChildren
SortChildrenCb
Toggle

TreeViewEx: Instance properties

Name Is Tested
AutoHScroll
Checkboxes
ContextMenuActive X
DimmedCheckboxes
DisableDragDrop
DoubleBuffer
DrawImageAsync
EditLabels
Enabled X
ExclusionCheckboxes
FadeInOutExpandos
FullRowselect
Gui X
HandlerChildrenGet
HandlerGetDispInfo
HandlerImageGet
HandlerImageSet
HandlerNameGet
HandlerNameSet
HandlerSelectedImageGet
HandlerSelectedImageSet
HandlerSetDispInfo
HasButtons
HasLines
Infotip
LinesAtRoot
MultiSelect
NoHScroll
NoIndentState
NonEvenHeight
NoScroll
NoSingleCollapse
NoTooltips
PartialCheckboxes
RichTooltip
RtlReading
ShowSelAlways
SingleExpand
TrackSelect
TvexTab X
Visible X

TreeViewEx - Tested notification handlers

TreeViewEx currently offers three sets of notification handlers, each using a different approach to managing the item collection on our side of the code.

TreeViewEx - Tested notification handlers - Node

These are the functions in file "src\notify-node.ahk". They get the node object by calling TreeViewEx.Prototype.GetNode(Handle), which calls TreeViewExObj.NodeConstructor(Handle).

Name Is Tested
TreeViewEx_HandlerBeginLabelEdit_Node
TreeViewEx_HandlerDeleteItem_Node
TreeViewEx_HandlerEndLabelEdit_Node
TreeViewEx_HandlerGetDispInfo_Node
TreeViewEx_HandlerGetInfoTip_Node
TreeViewEx_HandlerItemChanged_Node
TreeViewEx_HandlerItemChanging_Node
TreeViewEx_HandlerItemExpanded_Node
TreeViewEx_HandlerItemExpanding_Node
TreeViewEx_HandlerSetDispInfo_Node
TreeViewEx_HandlerSingleExpand_Node

TreeViewEx - Tested notification handlers - Node_C

These are the functions in file "src\notify-node-c.ahk". They get the node object by calling TreeViewEx.Prototype.GetNode_C(Handle), which accesses TreeViewExObj.Collection.Get(Handle).

Name Is Tested
TreeViewEx_HandlerBeginLabelEdit_Node_C
TreeViewEx_HandlerDeleteItem_Node_C
TreeViewEx_HandlerEndLabelEdit_Node_C
TreeViewEx_HandlerGetDispInfo_Node_C
TreeViewEx_HandlerGetInfoTip_Node_C
TreeViewEx_HandlerItemChanged_Node_C
TreeViewEx_HandlerItemChanging_Node_C
TreeViewEx_HandlerItemExpanded_Node_C
TreeViewEx_HandlerItemExpanding_Node_C
TreeViewEx_HandlerSetDispInfo_Node_C
TreeViewEx_HandlerSingleExpand_Node_C

TreeViewEx - Tested notification handlers - Node_Ptr

These are the functions in file "src\notify-node-ptr.ahk". They get the node object by calling node := ObjFromPtrAddRef(struct.lParam).

Name Is Tested
TreeViewEx_HandlerBeginLabelEdit_Node_Ptr X
TreeViewEx_HandlerDeleteItem_Node_Ptr X
TreeViewEx_HandlerEndLabelEdit_Node_Ptr X
TreeViewEx_HandlerGetDispInfo_Node_Ptr X
TreeViewEx_HandlerGetInfoTip_Node_Ptr X
TreeViewEx_HandlerItemChanged_Node_Ptr X
TreeViewEx_HandlerItemChanging_Node_Ptr X
TreeViewEx_HandlerItemExpanded_Node_Ptr X
TreeViewEx_HandlerItemExpanding_Node_Ptr X
TreeViewEx_HandlerSetDispInfo_Node_Ptr X
TreeViewEx_HandlerSingleExpand_Node_Ptr

TreeViewEx_Node

Each instance of TreeViewEx_Node has a property "Handle" which is set with the HTREEITEM handle. This is the same value as the ItemID parameter used by various TreeView methods as described in the AutoHotkey documentation. For example, the first parameter of TreeView.Prototype.Modify, expects an HTREEITEM handle. When you call a method or access a property from a TreeViewEx_Node instance, in most cases it calls a function which sends a TVM message where the wParam or lParam is expected to be an HTREEITEM handle.

Extending TreeViewEx_Node

TreeViewEx_Node is intended to be extended and coupled with callback functions passed to TreeViewEx.Prototype.OnNotify. This allows our code to reduce memory overhead and increase customizability by controlling characteristics of the tree-view items dynamically.

This section needs more work and there may be some delay before I get back to writing it. Use the demo file as a guide, and if something is unclear or you have a question, message @Cebolla on AutoHotkey.com.

TVN_GETDISPINFO

For TVN_GETDISPINFO notifications, your function is expected to fill the members of the TVITEMW structure with the requested information. Your code does not need to calculate any of the byte offsets, this is already done for you by the TvDispInfoEx class. Your code can simply assign a value to the appropriate property.

TVN_GETDISPINFO is only sent if the relevant member of a tree-view item's TVITEMW structure has been set with a specific value:

  • The pszText member of the item's TVITEMW structure is the LPSTR_TEXTCALLBACK value (-1).
  • The iImage member of the item's TVITEMW structure is the I_IMAGECALLBACK value (-1).
  • The iSelectedImage member of the item's TVITEMW structure is the I_IMAGECALLBACK value (-1).
  • The cChildren member of the item's TVITEMW structure is the I_CHILDRENCALLBACK value (-1).

TVN_SETDISPINFO

TVN_SETDISPINFO is only sent if the relevant member of a tree-view item's TVITEMW structure has been set with a specific value. Unlike TVN_GETDISPINFO which has four related members, TVN_SETDISPINFO only has three:

  • The pszText member of the item's TVITEMW structure is the LPSTR_TEXTCALLBACK value (-1).
  • The iImage member of the item's TVITEMW structure is the I_IMAGECALLBACK value (-1).
  • The iSelectedImage member of the item's TVITEMW structure is the I_IMAGECALLBACK value (-1).

The tree-view control sends TVN_SETDISPINFO notifications to inform your code that an event occurred that caused a change to a characteristic of a tree-view item. Typically the events are raised by the user's actions. The notification provides information about what characteristic was changed, and provides the new value.

The following are the contexts in which the tree-view control sends TVN_SETDISPINFO:

  • If the pszText member of the item's The user edits the label of an item (if this functionality is enabled for the control). The mask member will have the TVIF_FLAG set.
  • An item's selected state has changed. If the item's selected state has changed from being selected to being not selected, the mask member will have the TVIF_IMAGE flag set. If the item's selected state has changed from being not selected to being selected, the mask member will have the TVIF_SELECTEDIMAGE flag set.

TreeViewEx_Node: Tested methods and properties

The following is a list of methods and properties. The items with an "X" next to them have been tested. The items with no "X" have not been tested. Most of the methods and properties probably work, but only the marked items have been verified.

TreeViewEx_Node: Static methods

Name Is Tested
SetChildrenHandler
SetNameHandler
SetImageHandler
SetSelectedImageHandler

TreeViewEx_Node: Instance methods

Name Is Tested
__New
AddChild
Copy
CopyItemId
Collapse
CollapseReset
CreateDragImage
EnsureVisible
EnumChildren
EnumChildrenRecursive
Expand
ExpandPartial
GetItemState
GetText
MapHTreeItemToAccId
Select
SetInsertMark
SetTreeView
ShowInfoTip
SortChildren
SortChildrenCb
Toggle

TreeViewEx_Node: Instance properties

Name Is Tested
Child
Ctrl
Gui
InfoChildren
InfoImage
InfoName
InfoSelectedImage
IsParent
IsRoot
LineRect
Next
Parent
Previous
Root
Rect

About

An AutoHotkey (AHK) library that implements a custom tree-view control.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published