|
Post by (X) on Sept 15, 2023 4:38:48 GMT 1
In GFA_BASIC 32 for Windows, we have access to OCX and Non-OCX versions of every control. You can use either in a main program but you can't use OCX controls in a GLL (Gfa Link Library) extension used to enhance the GFA Editor.
Perhaps a "bummer", but, not a show stopper!
Non-OCX programming may make life a bit more difficult for the coder but it also reveals the world of Window Messages and the potential to customize a control's behaviour to your liking.
Here is a list of distinctly named Non-OCX controls (some ending with Ctrl) from the GB32 Help Documentation: These commands create controls without an OCX wrapper; so they cannot be handled using properties, methods, and event subs.
When used in a form the WM_NOTIFY message should be handled in the form's _MessageProc sub. (See Help Doc for more explanation.)
Here is my simple demo of a non-OCX version of a treeview control: TreeViewCtrl.
It shows how to insert:{Root, Branch and Child} items. I want to further develop this into an easy to manage template so anyone can add treeview functionality to their GLLs. This opens the door to sophisticated GFA Editor Enhancements that are limited only by our imagination.
'################################################################################# ' ' DISCLAIMER: THIS CODE IS OFFERED AS IS FOR EDUCATIONAL PURPOSES. ' YOU ARE FREE TO USE, COPY AND DISTRIBUTE. ' THE USE OF THIS CODE IS AT YOUR OWN RISK. ' I ACCEPT NO LIABILITY NOR MAKE ANY CLAIM OF ' CORRECTNESS OR SUITABILITY IN PART OR IN WHOLE. ' '################################################################################# ' ' FILENAME Demo TreeViewCtrl.G32 ' ' DESCRIPTION A demonstration of the use of a non-OCX Treeview control ' ' AUTHOR (X) ' EMAIL xman.gb32@gmail.com ' WEBSITE https://gfabasic32.blogspot.com/ ' FORUM https://gb32.proboards.com/ ' STARTED 2023-09-15 ' UPDATED <ISO date> ' ' $ManifestOff $Library "GfaWinX" $Library "UpdateRT" UpdateRuntime Mode Date "-"
P_Init LoadForm frm1
Do Sleep Until Me Is Nothing
Sub frm1_Load P_TVC_Create EndSub
Proc P_Init '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Each control created needs an Id index that I will store in a global variable ' called iCTL. It will serve to hold the current control identification index ' and can easily be incremented with an increment procedure: ' P_Increment_iCTL ' Global iCTL As Long = 100 Global Const TVIF_TEXT = 0x1 Global Const TVIF_IMAGE = 0x2 Global Const TVIF_SELECTEDIMAGE = 0x4 Global Const TVIF_STATE = 0x8 Global Const TVIF_PARAM = 0x10 Global Const TVIF_CHILDREN = 0x20 Global Const TVI_ROOT = 0x0 Global Const TVI_FIRST = 0x1 Global Const TVI_LAST = 0x2 Global Const TVI_SORT = 0x3 Global Const TVM_GETITEM = 0x110C Global Const TVM_SETITEM = 0x110D Global Const TVM_INSERTITEM = 0x1100 Global Const TVM_DELETEITEM = 0x1101 Global Const TVM_EXPAND = 0x1102 Global Const TVM_GETNEXTITEM = 0x110A Global Const TVM_SELECTITEM = 0x110B Global Const TVM_ENSUREVISIBLE = 0x1114 Global Const TVM_GETCOUNT = 0x1105 Global Const TVM_GETEDITCONTROL = 0x110F Global Const TVM_GETVISIBLECOUNT = 0x1110 Global Const TVM_HITTEST = 0x1111 Global Const TVM_SORTCHILDREN = 0x1113 Global Const TVM_SORTCHILDRENCB = 0x1115 Global Const TVM_GETIMAGELIST = 0x1109 Global Const TVM_SETIMAGELIST = 0x1108 Global Const TVM_GETISEARCHSTRING = 0x1116 Global Const TVS_HASBUTTONS = 0x1 Global Const TVS_HASLINES = 0x2 Global Const TVS_LINESATROOT = 0x4 Global Const TVS_EDITLABELS = 0x8 Global Const TVS_DISABLEDRAGDROP = 0x10 Global Const TVS_SHOWSELALWAYS = 0x20 Global Const TVS_CHECKBOXES = 0x100 Global Const TVS_TRACKSELECT = 0x200 Global Const TVS_SINGLEEXPAND = 0x400 Global Const TVS_INFOTIP = 0x800 Global Const WS_BORDER = 0x800000 Global Const WS_CAPTION = 0xC00000 Global Const WS_CHILD = 0x40000000 Global Const WS_CLIPCHILDREN = 0x2000000 Global Const WS_CLIPSIBLINGS = 0x4000000 Global Const WS_DISABLED = 0x8000000 Global Const WS_DLGFRAME = 0x400000 Global Const WS_GROUP = 0x20000 Global Const WS_HSCROLL = 0x100000 Global Const WS_MAXIMIZE = 0x1000000 Global Const WS_MAXIMIZEBOX = 0x10000 Global Const WS_MINIMIZE = 0x20000000 Global Const WS_MINIMIZEBOX = 0x20000 Global Const WS_OVERLAPPED = 0x0 Global Const WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED Or WS_CAPTION Or WS_SYSMENU Or WS_THICKFRAME Or WS_MINIMIZEBOX Or WS_MAXIMIZEBOX) Global Const WS_POPUP = 0x80000000 Global Const WS_POPUPWINDOW = (WS_POPUP Or WS_BORDER Or WS_SYSMENU) Global Const WS_SIZEBOX = 0x40000 Global Const WS_SYSMENU = 0x80000 Global Const WS_TABSTOP = 0x10000 Global Const WS_THICKFRAME = 0x40000 Global Const WS_VISIBLE = 0x10000000 Global Const WS_VSCROLL = 0x200000 Global Const WS_EX_DLGMODALFRAME = 0x1 Global Const WS_EX_NOPARENTNOTIFY = 0x4 Global Const WS_EX_TOPMOST = 0x8 Global Const WS_EX_ACCEPTFILES = 0x10 Global Const WS_EX_TRANSPARENT = 0x20 Global Const WS_EX_MDICHILD = 0x40 Global Const WS_EX_TOOLWINDOW = 0x80 Global Const WS_EX_WINDOWEDGE = 0x100 Global Const WS_EX_CLIENTEDGE = 0x200 Global Const WS_EX_CONTEXTHELP = 0x400 Global Const WS_EX_RIGHT = 0x1000 Global Const WS_EX_LEFT = 0x2000 Global Const WS_EX_RTLREADING = 0x2000 Global Const WS_EX_LTRREADING = 0x0 Global Const WS_EX_LEFTSCROLLBAR = 0x4000 Global Const WS_EX_RIGHTSCROLLBAR = 0x0 Global Const WS_EX_CONTROLPARENT = 0x10000 Global Const WS_EX_STATICEDGE = 0x20000 Global Const WS_EX_APPWINDOW = 0x40000 Global Const WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE Or WS_EX_CLIENTEDGE) Global Const WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE Or WS_EX_TOOLWINDOW Or WS_EX_TOPMOST) Global Const WS_EX_LAYERED = 0x80000 Global Const WS_EX_NOINHERITLAYOUT = 0x100000 Global Const WS_EX_LAYOUTRTL = 0x400000 Global Const WS_EX_COMPOSITED = 0x2000000 Global Const WS_EX_NOACTIVATE = 0x8000000 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Style shortcuts... ' Global Const STYLE1 = WS_TABSTOP Global Const STYLE2 = BS_DEFPUSHBUTTON | WS_TABSTOP Global Const STYLE3 = BS_GROUPBOX | WS_TABSTOP Global Const STYLE4 = BS_AUTORADIOBUTTON | WS_TABSTOP Global Const STYLE5 = BS_AUTOCHECKBOX | WS_TABSTOP Global Const STYLE6 = ES_UPPERCASE | WS_TABSTOP | WS_BORDER Global Const STYLE7 = LBS_NOTIFY | LBS_SORT | LBS_STANDARD | WS_BORDER | WS_VSCROLL Global Const STYLE8 = CBS_DROPDOWN | CBS_SORT | CBS_HASSTRINGS | WS_VSCROLL Global Const STYLE9 = SB_CTL | SB_BOTTOM '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' User defined type statements... ' // Apparently already defined in an included library... °Type RECT °Left As Long °Top As Long °Right As Long °Bottom As Long °End Type Type T_CTL -String * 40 name -String * 40 title -Long hWnd -Long i // Dialog structure number (0 to 31) -Long x // X coordinates of left corner of Dialog box -Long y // Y coordinates of upper corner of Dialog box -Long w // Dialog box width in pixels -Long h // Dialog box height in pixels -Long flag // WS_Style flags to be used by the Dialog -Long font_height // Font-height (normally negative) -String * 40 font_name // Typeface name of the font EndType Type T_TV_ITEM mask As Long ' Mask specifying which members of the structure are valid hItem As Long ' Handle of the tree-view item state As Long ' State of the item stateMask As Long ' Mask for state bits pszText As Long ' Pointer to the item's text (or LPSTR_TEXTCALLBACK) cchTextMax As Long ' Size of the buffer pointed to by pszText iImage As Long ' Index of the item's image iSelectedImage As Long ' Index of the item's selected image cChildren As Long ' Number of child items (0 if none) lParam As Long ' Application-specific data End Type Type T_TV_INSERT_STRUCT hParent As Long hInsertAfter As Long item As T_TV_ITEM End Type Type T_NMHDR hwndFrom As Long idFrom As Long code As Long EndType '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' API declarations... ' Declare Function MoveWindow Lib "user32" ( _ ByVal hWnd As Long, _ ByVal x As Long, _ ByVal y As Long, _ ByVal nWidth As Long, _ ByVal nHeight As Long, _ ByVal bRepaint As Long) As Long Declare Function GetClientRect Lib "user32" ( _ ByVal hWnd As Long, _ ByRef lpRect As RECT) As Long EndProc
Proc P_TVC_Create '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Create a non-OCX treeview control using TreeViewCtrl command... ' ' TVS_EDITLABELS | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | WS_CHILD | ' WS_OVERLAPPED | WS_VISIBLE | WS_VSCROLL Dim style% = _ TVS_EDITLABELS Or _ TVS_HASBUTTONS Or _ TVS_HASLINES Or _ TVS_LINESATROOT Or _ WS_CHILD Or _ WS_VISIBLE Or _ WS_VSCROLL ' WS_EX_CLIENTEDGE | WS_EX_LEFT style |= _ WS_EX_CLIENTEDGE Or _ WS_EX_LEFT Trace Hex(style, 8) Global TVC As T_CTL With TVC .i = iCTL .x = 10 .y = 10 .w = frm1.ScaleWidth - 20 .h = frm1.ScaleHeight - 20 .flag = style Trace Hex(.flag, 8) TreeViewCtrl "", .i, .x, .y, .w, .h, .flag .hWnd = Dlg(frm1.hWnd, .i) P_SetFont(frm1.hWnd, .i, F_hFont_Consolas(16)) EndWith Trace TVC P_Increment_iCTL P_TVC_Init EndProc
Proc P_Increment_iCTL iCTL++ EndProc
Proc P_TVC_Init() Trace "" '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Initialize the treeview control... ' Dim iNode% Dim iRoot% = F_TVC_Insert_Item("Root") iNode = F_TVC_Insert_Item("Branch", iRoot) iNode = F_TVC_Insert_Item("Branch2", iRoot) iNode = F_TVC_Insert_Item("Branch3", iNode) EndProc
Function F_TVC_Insert_Item(txt$, Optional iParent% = TVI_ROOT, Optional iImg% = 0, Optional iSelImg% = 0) As Long Dim tvItem As T_TV_ITEM With tvItem .mask = TVIF_TEXT Or TVIF_IMAGE Or TVIF_SELECTEDIMAGE Or TVIF_PARAM .hItem = TVI_LAST .pszText = V:txt$ .cchTextMax = Len(txt$) .iImage = iImg .iSelectedImage = iSelImg EndWith Trace tvItem Dim insertStruct As T_TV_INSERT_STRUCT With insertStruct .hParent = iParent .hInsertAfter = TVI_FIRST .item = tvItem EndWith
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Insert an item into the treeview relative to the specified parent item index. ' F_TVC_Insert_Item = SendMessage(TVC.hWnd, TVM_INSERTITEM, 0, V:insertStruct) EndFunc
Sub frm1_MessageProc(hWnd%, Mess%, wParam%, lParam%, retval%, ValidRet?) Dim hdr As Pointer T_NMHDR Select Mess% Case WM_NOTIFY Pointer(hdr) = lParam Trace hdr //.idfrom EndSelect EndSub
Proc P_SetFont(hWnd%, iControl%, hFNT%) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Set the font of the index specified control and Dialog handle (essentially the ' main form) ' Dim hCTL% = DlgItem(hWnd, iControl) Dim Redraw? = True SendMessage hCTL, WM_SETFONT, hFNT, Redraw? EndProc
Function F_hFont_Consolas(font_size% ) As Handle Return CreateFont(-font_size, 0, 0, 0, _ FW_NORMAL, 0, 0, 0, _ DEFAULT_CHARSET, _ OUT_DEFAULT_PRECIS, _ CLIP_DEFAULT_PRECIS, _ DEFAULT_QUALITY, _ DEFAULT_PITCH Or FF_DONTCARE, _ "Consolas") EndFunc
This is the demo from the Help Doc:
Form frm
TreeViewCtrl "", 10, 20, 20, 150, 200
Do Sleep Until Me Is Nothing
Sub frm_MessageProc(hWnd%, Mess%, wParam%, lParam%, retval%, ValidRet?) Dim hdr As Pointer NMHDR Switch Mess Case WM_NOTIFY Pointer(hdr) = lParam Print hdr.idfrom EndSwitch EndSub
Type NMHDR hwndFrom As Long idfrom As Long code As Long EndType
|
|
|
Post by (X) on Sept 17, 2023 1:33:18 GMT 1
I've added code to Sort, Delete and Rename treeview items...
'################################################################################# ' ' DISCLAIMER: THIS CODE IS OFFERED AS IS FOR EDUCATIONAL PURPOSES. ' YOU ARE FREE TO USE, COPY AND DISTRIBUTE. ' THE USE OF THIS CODE IS AT YOUR OWN RISK. ' I ACCEPT NO LIABILITY NOR MAKE ANY CLAIM OF ' CORRECTNESS OR SUITABILITY IN PART OR IN WHOLE. ' '################################################################################# ' ' FILENAME Demo TreeViewCtrl.G32 ' ' DESCRIPTION A demonstration of the use of a non-OCX Treeview control ' ' AUTHOR (X) ' EMAIL xman.gb32@gmail.com ' WEBSITE https://gfabasic32.blogspot.com/ ' FORUM https://gb32.proboards.com/ ' STARTED 2023-09-15 Worked out the mechanics of inserting an item into the treeview. ' UPDATED 2023-09-16 Organizing and Consolidating the code. ' ' $ManifestOff $Library "GfaWinX" $Library "UpdateRT" UpdateRuntime
P_Main $Group "NOTES" Proc Notes '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' This is where I will keep notes and code snips to guide me along. ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' You can use the `SendMessage` function to send messages to a non-OCX treeview ' control and retrieve information about its nodes ¹². The `SendMessage` ' function sends the specified message to a window or windows and then returns ' immediately³. Here is an example of how you can use the `SendMessage` ' function to retrieve information about each node in a non-OCX treeview control: ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' //////////////////////////////////////////////////////////////////////////////// // Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long // // Private Const TV_FIRST = &H1100 // Private Const TVM_GETNEXTITEM = (TV_FIRST + 10) // Private Const TVGN_ROOT = 0 // Private Const TVGN_NEXT = 1 // Private Const TVGN_CHILD = 4 // // Private Sub PrintNodes(ByVal hWnd As Long, ByVal hItem As Long, ByVal level As Integer) // Dim tvItem As TV_ITEM // Dim childItem As Long // // ' Initialize the TV_ITEM structure // tvItem.mask = TVIF_TEXT // tvItem.hItem = hItem // tvItem.pszText = String$(255, vbNullChar) // tvItem.cchTextMax = Len(tvItem.pszText) - 1 // // ' Get the text of the current node // SendMessage hWnd, TVM_GETITEM, 0, tvItem // // ' Print information about the current node // Debug.Print "Index: " & hItem & ", Parent Index: " & level & ", Value: " & Left$(tvItem.pszText, tvItem.cchText) // // ' Recursively print information about each child node // childItem = SendMessage(hWnd, TVM_GETNEXTITEM, TVGN_CHILD, hItem) // // Do While childItem <> 0 // PrintNodes hWnd, childItem, hItem // childItem = SendMessage(hWnd, TVM_GETNEXTITEM, TVGN_NEXT, childItem) // Loop // End Sub //////////////////////////////////////////////////////////////////////////////// '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' In this example, the `PrintNodes` subroutine takes three parameters: ' `hWnd`, which is the handle of the treeview control; `hItem`, which is the ' handle of the current node; and `level`, which is the index of the parent ' node. The subroutine uses the `SendMessage` function to retrieve information ' about each node in the treeview control and prints its index, parent index, ' and value to the debug window. It then recursively calls itself with each ' child node and its own index as parameters. ' ' To call this subroutine for a non-OCX treeview control, you can pass the ' handle of the control and the handle of its root node as parameters. Here ' is an example of how you can do this: ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' //////////////////////////////////////////////////////////////////////////////// // Private Sub PrintTreeView(ByVal hWnd As Long) // Dim rootItem As Long // // ' Get the handle of the root item // rootItem = SendMessage(hWnd, TVM_GETNEXTITEM, TVGN_ROOT, 0) // // ' Print information about each node in the treeview control // PrintNodes hWnd, rootItem, -1 // End Sub //////////////////////////////////////////////////////////////////////////////// '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' In this example, the `PrintTreeView` subroutine takes one parameter: ' `hWnd`, which is the handle of the treeview control. The subroutine uses ' the `SendMessage` function to get the handle of the root item and then ' calls the `PrintNodes` subroutine with that handle and a parent index ' of -1 to print information about each node in the treeview control. ' ' I hope this helps! ' ' Source: Conversation with Bing, 9/15/2023 ' (1) Loop through treeview parent and child nodes - Stack Overflow. ' https://stackoverflow.com/questions/48999341/ ' loop-through-treeview-parent-and-child-nodes. ' (2) [Solved]-Loop through treeview parent and child nodes-VBA Excel. ' https://www.appsloveworld.com/vba/300/305/ ' loop-through-treeview-parent-and-child-nodes. ' (3) How to Iterate through all nodes of a treeView Control. C#. ' https://stackoverflow.com/questions/19691286/ ' how-to-iterate-through-all-nodes-of-a-treeview-control-c-sharp. ' (4) mfc - How to iterate through all parent nodes of treeview control in .... ' https://stackoverflow.com/questions/32655497/ ' how-to-iterate-through-all-parent-nodes-of-treeview-control-in-c. ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' ' Q: In vb6 treeview code: ' ° Dim insertStruct As T_TV_INSERT_STRUCT ° ° With insertStruct ° .hParent = iParent ° .hInsertAfter = iOrder ° .item = tvItem ° EndWith ' ' This insertstruc .hInsertAfter tells the treeview control where to insert the ' item root, first, last sorted. How is this reconciled with the item record ' information .hItem? ' ' In the VB6 TreeView control, `.hInsertAfter` and `.hItem` serve different ' purposes: ' `.hInsertAfter` is used to specify the location where the new item should ' be inserted in relation to its siblings². It can take values like `TVI_FIRST`, ' `TVI_LAST`, `TVI_SORT`, or the handle of an existing item. For example, if ' `.hInsertAfter = TVI_LAST`, the new item will be inserted at the end of the ' list of its siblings². ' ' `.hItem`, on the other hand, is used to specify a particular item in the ' tree when you want to modify or retrieve information about that item¹. It's ' essentially a unique identifier for each item in the tree. ' ' So, while `.hItem` identifies an item, `.hInsertAfter` determines where a ' new item will be placed in relation to other items. They work together to ' allow you to manipulate and organize the items in your TreeView control. ' ' Q: So, when you are inserting, the hItem value in the TV_Item record is ignored? ' ' Yes, that's correct. When you're inserting a new item into the TreeView ' control, the `.hItem` value in the `TV_ITEM` structure is ignored. The ' `TV_INSERTSTRUCT` structure uses the `.hInsertAfter` and `.hParent` values ' to determine where the new item should be placed. The `TV_ITEM` structure ' is included in the `TV_INSERTSTRUCT` as `.item`, and it contains information ' about the item itself, such as its text and image. But its `.hItem` value ' isn't used when inserting a new item. ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' You can indeed use `TVI_SORT` for `.hInsertAfter` when inserting items to ' request that the TreeView control sorts the siblings automatically. However, ' there's a caveat to consider. ' When you use `TVI_SORT`, the TreeView control will sort the items based on ' their text automatically, which can be convenient. However, it can also lead ' to some unexpected behavior if you're not careful. The sorting is done based ' on the text of the items, and it can reorder the items immediately after ' insertion, which may not be what you want in all cases. ' ' If you're sure that you always want the items sorted alphabetically by their ' text, then using `TVI_SORT` can simplify your code. However, if you have ' specific sorting requirements or if you need to insert items in a specific ' order that doesn't match the text, you may want to use `TVI_FIRST` or ' `TVI_LAST` and then explicitly call `TVM_SORTCHILDREN` as needed after ' all the items are inserted. This approach gives you more control over ' the sorting process. ' EndProc
$Group "FUNCTIONS" Function F_hFnt_Consolas(font_size%) As Handle Return CreateFont(-font_size, 0, 0, 0, _ FW_NORMAL, 0, 0, 0, _ DEFAULT_CHARSET, _ OUT_DEFAULT_PRECIS, _ CLIP_DEFAULT_PRECIS, _ DEFAULT_QUALITY, _ DEFAULT_PITCH Or FF_DONTCARE, _ "Consolas") EndFunc
$Group "PROCEDURES" Proc P_Inc_iCTL iCTL++ EndProc
Proc P_Init '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Each control created needs an Id index that I will store in a global variable ' called iCTL. It will serve to hold the current control identification index ' and can easily be incremented with an increment procedure: ' P_Inc_iCTL ' Global iCTL As Long = 100 Global Const TVGN_ROOT = 0x0 Global Const TVGN_NEXT = 0x1 Global Const TVGN_CHILD = 0x4 Global Const TVIF_TEXT = 0x1 Global Const TVIF_IMAGE = 0x2 Global Const TVIF_SELECTEDIMAGE = 0x4 Global Const TVIF_STATE = 0x8 Global Const TVIF_PARAM = 0x10 Global Const TVIF_CHILDREN = 0x20 Global Const TVI_ROOT = 0x0 Global Const TVI_FIRST = 0x1 Global Const TVI_LAST = 0x2 Global Const TVI_SORT = 0x3 Global Const TVM_GETITEM = 0x110C Global Const TVM_SETITEM = 0x110D Global Const TVM_INSERTITEM = 0x1100 Global Const TVM_DELETEITEM = 0x1101 Global Const TVM_EXPAND = 0x1102 Global Const TVM_GETNEXTITEM = 0x110A Global Const TVM_SELECTITEM = 0x110B Global Const TVM_ENSUREVISIBLE = 0x1114 Global Const TVM_GETCOUNT = 0x1105 Global Const TVM_GETEDITCONTROL = 0x110F Global Const TVM_GETVISIBLECOUNT = 0x1110 Global Const TVM_HITTEST = 0x1111 Global Const TVM_SORTCHILDREN = 0x1113 Global Const TVM_SORTCHILDRENCB = 0x1115 Global Const TVM_GETIMAGELIST = 0x1109 Global Const TVM_SETIMAGELIST = 0x1108 Global Const TVM_GETISEARCHSTRING = 0x1116 Global Const TVS_HASBUTTONS = 0x1 Global Const TVS_HASLINES = 0x2 Global Const TVS_LINESATROOT = 0x4 Global Const TVS_EDITLABELS = 0x8 Global Const TVS_DISABLEDRAGDROP = 0x10 Global Const TVS_SHOWSELALWAYS = 0x20 Global Const TVS_CHECKBOXES = 0x100 Global Const TVS_TRACKSELECT = 0x200 Global Const TVS_SINGLEEXPAND = 0x400 Global Const TVS_INFOTIP = 0x800 Global Const WS_BORDER = 0x800000 Global Const WS_CAPTION = 0xC00000 Global Const WS_CHILD = 0x40000000 Global Const WS_CLIPCHILDREN = 0x2000000 Global Const WS_CLIPSIBLINGS = 0x4000000 Global Const WS_DISABLED = 0x8000000 Global Const WS_DLGFRAME = 0x400000 Global Const WS_GROUP = 0x20000 Global Const WS_HSCROLL = 0x100000 Global Const WS_MAXIMIZE = 0x1000000 Global Const WS_MAXIMIZEBOX = 0x10000 Global Const WS_MINIMIZE = 0x20000000 Global Const WS_MINIMIZEBOX = 0x20000 Global Const WS_OVERLAPPED = 0x0 Global Const WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED Or WS_CAPTION Or WS_SYSMENU Or WS_THICKFRAME Or WS_MINIMIZEBOX Or WS_MAXIMIZEBOX) Global Const WS_POPUP = 0x80000000 Global Const WS_POPUPWINDOW = (WS_POPUP Or WS_BORDER Or WS_SYSMENU) Global Const WS_SIZEBOX = 0x40000 Global Const WS_SYSMENU = 0x80000 Global Const WS_TABSTOP = 0x10000 Global Const WS_THICKFRAME = 0x40000 Global Const WS_VISIBLE = 0x10000000 Global Const WS_VSCROLL = 0x200000 Global Const WS_EX_DLGMODALFRAME = 0x1 Global Const WS_EX_NOPARENTNOTIFY = 0x4 Global Const WS_EX_TOPMOST = 0x8 Global Const WS_EX_ACCEPTFILES = 0x10 Global Const WS_EX_TRANSPARENT = 0x20 Global Const WS_EX_MDICHILD = 0x40 Global Const WS_EX_TOOLWINDOW = 0x80 Global Const WS_EX_WINDOWEDGE = 0x100 Global Const WS_EX_CLIENTEDGE = 0x200 Global Const WS_EX_CONTEXTHELP = 0x400 Global Const WS_EX_RIGHT = 0x1000 Global Const WS_EX_LEFT = 0x2000 Global Const WS_EX_RTLREADING = 0x2000 Global Const WS_EX_LTRREADING = 0x0 Global Const WS_EX_LEFTSCROLLBAR = 0x4000 Global Const WS_EX_RIGHTSCROLLBAR = 0x0 Global Const WS_EX_CONTROLPARENT = 0x10000 Global Const WS_EX_STATICEDGE = 0x20000 Global Const WS_EX_APPWINDOW = 0x40000 Global Const WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE Or WS_EX_CLIENTEDGE) Global Const WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE Or WS_EX_TOOLWINDOW Or WS_EX_TOPMOST) Global Const WS_EX_LAYERED = 0x80000 Global Const WS_EX_NOINHERITLAYOUT = 0x100000 Global Const WS_EX_LAYOUTRTL = 0x400000 Global Const WS_EX_COMPOSITED = 0x2000000 Global Const WS_EX_NOACTIVATE = 0x8000000 '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Style shortcuts... ' Global Const STYLE1 = WS_TABSTOP Global Const STYLE2 = BS_DEFPUSHBUTTON | WS_TABSTOP Global Const STYLE3 = BS_GROUPBOX | WS_TABSTOP Global Const STYLE4 = BS_AUTORADIOBUTTON | WS_TABSTOP Global Const STYLE5 = BS_AUTOCHECKBOX | WS_TABSTOP Global Const STYLE6 = ES_UPPERCASE | WS_TABSTOP | WS_BORDER Global Const STYLE7 = LBS_NOTIFY | LBS_SORT | LBS_STANDARD | WS_BORDER | WS_VSCROLL Global Const STYLE8 = CBS_DROPDOWN | CBS_SORT | CBS_HASSTRINGS | WS_VSCROLL Global Const STYLE9 = SB_CTL | SB_BOTTOM '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' User defined type statements... ' // Apparently already defined in an included library... ' Type RECT ' Left As Long ' Top As Long ' Right As Long ' Bottom As Long ' End Type Type T_CTL -String * 40 name -String * 40 title -Long hWnd -Long i // Dialog structure number (0 to 31) -Long x // X coordinates of left corner of Dialog box -Long y // Y coordinates of upper corner of Dialog box -Long w // Dialog box width in pixels -Long h // Dialog box height in pixels -Long flag // WS_Style flags to be used by the Dialog -Long font_height // Font-height (normally negative) -String * 40 font_name // Typeface name of the font EndType Type T_TV_ITEM mask As Long ' Mask specifying which members of the structure are valid hItem As Long ' Handle of the tree-view item state As Long ' State of the item stateMask As Long ' Mask for state bits pszText As Long ' Pointer to the item's text (or LPSTR_TEXTCALLBACK) cchTextMax As Long ' Size of the buffer pointed to by pszText iImage As Long ' Index of the item's image iSelectedImage As Long ' Index of the item's selected image cChildren As Long ' Number of child items (0 if none) lParam As Long ' Application-specific data End Type Type T_TV_INSERT_STRUCT hParent As Long hInsertAfter As Long item As T_TV_ITEM End Type Type T_NMHDR hwndFrom As Long idFrom As Long code As Long EndType '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' API declarations... ' Declare Function MoveWindow Lib "user32" ( _ ByVal hWnd As Long, _ ByVal x As Long, _ ByVal y As Long, _ ByVal nWidth As Long, _ ByVal nHeight As Long, _ ByVal bRepaint As Long) As Long Declare Function GetClientRect Lib "user32" ( _ ByVal hWnd As Long, _ ByRef lpRect As RECT) As Long EndProc
Proc P_Main Mode Date "-" P_Init LoadForm frm1 Do Sleep Until Me Is Nothing EndProc
Proc P_PrintNodes(hWnd%, hItem%, level%) Dim tvItem As T_TV_ITEM Dim childItem As Long ' Initialize the TV_ITEM structure tvItem.mask = TVIF_TEXT tvItem.hItem = hItem Dim txt_bfr$ = String(255, Chr(0)) Dim s$ tvItem.pszText = V:txt_bfr tvItem.cchTextMax = 255 ' Get the text of the current node SendMessage hWnd, TVM_GETITEM, 0, tvItem s = ZTrim(txt_bfr) ' Print information about the current node Debug _ "Index: " & hItem & _ ", Parent Index: " & level _ & ", Value: " & tvItem.pszText _ & ", Value: " & tvItem.cchTextMax _ & ", Value: " & s & ", Len(s)=" & Len(s) ' Recursively print information about each child node childItem = SendMessage(hWnd, TVM_GETNEXTITEM, TVGN_CHILD, hItem) Do While childItem <> 0 P_PrintNodes hWnd, childItem, hItem childItem = SendMessage(hWnd, TVM_GETNEXTITEM, TVGN_NEXT, childItem) Loop EndProc
Proc P_PrintTreeView(hWnd%) Dim rootItem As Long ' Get the handle of the root item rootItem = SendMessage(hWnd, TVM_GETNEXTITEM, TVGN_ROOT, 0) ' Print information about each node in the treeview control P_PrintNodes hWnd, rootItem, -1 EndProc
Proc P_TV_Add( _ t$, _ Optional parent As String, _ Optional iOrder% = TVI_FIRST, _ Optional iImg% = 0, _ Optional iSelImg% = 0) Dim iParent% = Iif(IsMissing(parent), TVI_ROOT, hItem[parent]) Dim tvItem As T_TV_ITEM With tvItem .mask = TVIF_TEXT Or TVIF_IMAGE Or TVIF_SELECTEDIMAGE Or TVIF_PARAM .hItem = TVI_ROOT // Ignored for insert operation .pszText = V:t$ .cchTextMax = Len(t$) .iImage = iImg .iSelectedImage = iSelImg EndWith Trace tvItem Dim insertStruct As T_TV_INSERT_STRUCT With insertStruct .hParent = iParent .hInsertAfter = TVI_LAST // TVI_SORT seems to have no effect .item = tvItem EndWith Trace insertStruct Trace TV.hWnd '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Insert an item into the treeview relative to the specified parent item index. ' hItem[t$] = SendMessage(TV.hWnd, TVM_INSERTITEM, 0, V:insertStruct) Trace hItem["Root"] '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Sort the children since TVI_SORT in the insertStruct seems to have no effect. ' If (iOrder% == TVI_SORT) ~SendMessage(TV.hWnd, TVM_SORTCHILDREN, 0, iParent) EndIf EndProc
Proc P_TV_Create '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Create a non-OCX treeview control using TreeViewCtrl command... ' Dim style% = _ TVS_EDITLABELS Or _ TVS_HASBUTTONS Or _ TVS_HASLINES Or _ TVS_LINESATROOT Or _ WS_CHILD Or _ WS_VISIBLE Or _ WS_VSCROLL Dim style_ex% = _ WS_EX_CLIENTEDGE Or _ WS_EX_LEFT style |= style_ex Trace Hex(style, 8) Global TV As T_CTL With TV .i = iCTL P_Inc_iCTL .x = 10 .y = 10 .w = frm1.ScaleWidth - 20 .h = frm1.ScaleHeight - 20 .flag = style TreeViewCtrl "", .i, .x, .y, .w, .h, .flag .hWnd = Dlg(frm1.hWnd, .i) P_SetFont(TV.hWnd, F_hFnt_Consolas(24)) EndWith P_TV_Init EndProc
Proc P_TV_Del(hTV%, t$) SendMessage hTV, TVM_DELETEITEM, 0, hItem[t$] EndProc
Proc P_TV_Ren(hTV%, t$, newName$) Dim tvItem As T_TV_ITEM tvItem.mask = TVIF_TEXT tvItem.hItem = hItem[t$] tvItem.pszText = V:newName tvItem.cchTextMax = Len(newName) + 1 ' Include space for null terminator SendMessage hTV, TVM_SETITEM, 0, tvItem EndProc
Proc P_TV_Init() Trace "" '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Initialize the treeview control... ' To insert a root item, you can set: ' hParent to TVI_ROOT and ' hInsertAfter to TVI_FIRST. ' ' To insert a sibling branch, you can set: ' hParent to the handle of an existing parent item and ' hInsertAfter to the handle of an existing sibling item. ' ' To insert a child sub-branch, you can set: ' hParent to the handle of an existing parent item and ' hInsertAfter to one of the following values: ' TVI_FIRST Inserts the item at the beginning of the list. ' TVI_LAST Inserts the item at the end of the list. ' TVI_SORT Inserts the item in alphabetical order. ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' A Hash table can store a value of Variant type or of a specific type. ' The reason for a specific type may be to better validate the values or simply to ' optimize for less memory and or disk space and/or better data throughput. ' Hash Table entries require a unique string that acts like a key to unlock the ' data value stored in a kind of locker, so, if a data value was assigned "some_key", ' this can be used to retrieve the data value assigned to it using the syntax: ' <some var> = hItemI["some_key"] ' ' As for the treeview control, its items or node records contain the string entry ' and the image indices that we may wish to delete or modify. This requires the ' unique index of the treeview item that is assigned to it. It is worth noting ' that these indices may change once a treeview data set has been reordered or ' item(s) deleted. ' ' So, we need to account for two scenarios. ' 1) We are doing things from code. ' 2) We are interacting with a user clicking on the treeview control. ' Global hItem As Hash Long Dim iNode% Dim iRoot% Dim t$ = "ROOT" P_TV_Add("Root") P_TV_Add("Root3") P_TV_Add("Branch3", "Root3", TVI_SORT) P_TV_Add("Branch2", "Root3", TVI_SORT) P_TV_Add("Sibling2", "Branch3") P_TV_Add("Sibling1", "Branch3") P_TV_Add("Sibling4", "Branch3") P_TV_Add("Child", "Sibling1") P_TV_Add("TEST") P_TV_Add("Root2", , TVI_SORT) P_TV_Add("Root4" ) 'P_TV_Del(TV.hWnd, "Root4") P_TV_Del(TV.hWnd, "Child") P_TV_Add("Child1", "Sibling2") P_TV_Ren(TV.hWnd, "Child1", "Enfant1") 'P_PrintTreeView(TV.hWnd) EndProc
Proc P_SetFont(hWnd%, hFnt%) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Set the font of the specified control via its window handle... ' Dim Redraw? = True SendMessage hWnd, WM_SETFONT, hFnt, Redraw? EndProc
$Group "SUBROUTINES" Sub frm1_Load frm1.Caption = App.Name P_TV_Create EndSub
Sub frm1_MessageProc(hWnd%, Mess%, wParam%, lParam%, retval%, ValidRet?) Dim hdr As Pointer T_NMHDR Select Mess% Case WM_NOTIFY Pointer(hdr) = lParam 'Trace hdr //.idfrom EndSelect EndSub
|
|