Explains why the classic Win32 TreeView control offers separate sort methods for name and lParam, and recommends switching to a data model pattern when both are needed for sorting.
<p>The Win32 TreeView control in the common controls library provides two ways of sorting elements.</p>
<ul>
<li><code>TVM_SORTCHILDREN</code>: Sorts children alphabetically by name.</li>
<li><code>TVM_SORTCHILDRENCB</code>: Sorts children via custmm callback.</li>
</ul>
<p>The custom callback is provided the <code>lParam</code> of the two tree items being compared. But what if you want to sort by a combination of both the text and the <code>lParam</code>? How do you get both?</p>
<p>There are two general designs for using UI controls that represent collections.</p>
<p>One model is for the UI control to be the data repository. Everything you need to know about the item resides in the UI control, somewhere in its name, its check state, its selection state, whatever. If you need to know something about an item, you ask the UI control for the information.</p>
<p>The second model is for the data repository to be some sort of object that itself does not have any UI. (This is known in the biz as a “data model”.) You then construct UI elements to be the representation of those objects.</p>
<p>Windows controls generally lean toward the data model approach because there is usually a lot of information about an item that is not present in its UI representation. The data model approach also allows for optimizations in which where very large collections of items create UI elements only for the items that are visible on screen. You can see this in the XAML ListView control as well as in the classic Win32 ListView control when placed into owner-data mode.</p>
<p>For the controls in the common controls library, the general pattern is to provide a place to store a pointer-sized value that is not shown in the UI, typically called “item data” or just <code>lParam</code>. Here is where you store a pointer to the data model object that the UI object represents.</p>
<p>Okay, so let’s look at the TreeView sort methods again.</p>
<p>The <code>TVM_SORTCHILDRENCB</code> message takes a callback which is passed the <code>lParam</code>s of two items to compare. The theory is that these <code>lParam</code>s are pointers to larger data structures that describe the item, and you use those larger data structures to decide the ordering of the two items.</p>
<p>The <code>TVM_SORTCHILDREN</code> message doesn’t take a callback. It is a convenience method for the case where you are just sorting by name, so it uses the already-available name assigned to the item.</p>
<p>The case where you would need both is the case where the <code>lParam</code> is not enough to recover the name, either because it’s a pointer to a structure that doesn’t include a name, or because it’s not a pointer at all.</p>
<p>I can imagine running into this case if the only information you need to track for each TreeView item is its name and a pointer-sized piece of data. You put the name in the TreeView item text and the other data in the <code>lParam</code>. This plan works great until you need to sort the items, and your sort comparison function wants access to both pieces of data.</p>
<p>The solution is to switch to a data model pattern. Allocate a structure for each TreeView item and put the string and additional data in that structure. (Alternatively, you could just be sneaky and have the structure be the <code>HTREEITEM</code> and the additional data. Then you can recover the string by using the <code>TVM_<wbr />GETITEM</code> message.)</p>
<p><b>Bonus chatter</b>: In theory, the <code>TVM_SORTCHILDRENCB</code> could have passed the <code>HTREEITEM</code>s to the callback. The callback could then use the <code>HTREEITEM</code> to obtain both the string and the <code>lParam</code>. I suspect this didn’t happen because most callback functions would just ask for the <code>lParam</code> from the <code>HTREEITEM</code>, <code>TVM_SORTCHILDRENCB</code> is doing you a favor and saving you a bunch of work by giving you the thing you probably wanted in the first place.</p>
<p>The post <a href="https://devblogs.microsoft.com/oldnewthing/20260520-00/?p=112343">The classic TreeView control lets me sort by name or by lParam, but why not both?</a> appeared first on <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a>.</p>
# The classic TreeView control lets me sort by name or by lParam, but why not both? - The Old New Thing
Source: [https://devblogs.microsoft.com/oldnewthing/20260520-00?p=112343](https://devblogs.microsoft.com/oldnewthing/20260520-00?p=112343)
The Win32 TreeView control in the common controls library provides two ways of sorting elements\.
- `TVM\_SORTCHILDREN`: Sorts children alphabetically by name\.
- `TVM\_SORTCHILDRENCB`: Sorts children via custmm callback\.
The custom callback is provided the`lParam`of the two tree items being compared\. But what if you want to sort by a combination of both the text and the`lParam`? How do you get both?
There are two general designs for using UI controls that represent collections\.
One model is for the UI control to be the data repository\. Everything you need to know about the item resides in the UI control, somewhere in its name, its check state, its selection state, whatever\. If you need to know something about an item, you ask the UI control for the information\.
The second model is for the data repository to be some sort of object that itself does not have any UI\. \(This is known in the biz as a “data model”\.\) You then construct UI elements to be the representation of those objects\.
Windows controls generally lean toward the data model approach because there is usually a lot of information about an item that is not present in its UI representation\. The data model approach also allows for optimizations in which where very large collections of items create UI elements only for the items that are visible on screen\. You can see this in the XAML ListView control as well as in the classic Win32 ListView control when placed into owner\-data mode\.
For the controls in the common controls library, the general pattern is to provide a place to store a pointer\-sized value that is not shown in the UI, typically called “item data” or just`lParam`\. Here is where you store a pointer to the data model object that the UI object represents\.
Okay, so let’s look at the TreeView sort methods again\.
The`TVM\_SORTCHILDRENCB`message takes a callback which is passed the`lParam`s of two items to compare\. The theory is that these`lParam`s are pointers to larger data structures that describe the item, and you use those larger data structures to decide the ordering of the two items\.
The`TVM\_SORTCHILDREN`message doesn’t take a callback\. It is a convenience method for the case where you are just sorting by name, so it uses the already\-available name assigned to the item\.
The case where you would need both is the case where the`lParam`is not enough to recover the name, either because it’s a pointer to a structure that doesn’t include a name, or because it’s not a pointer at all\.
I can imagine running into this case if the only information you need to track for each TreeView item is its name and a pointer\-sized piece of data\. You put the name in the TreeView item text and the other data in the`lParam`\. This plan works great until you need to sort the items, and your sort comparison function wants access to both pieces of data\.
The solution is to switch to a data model pattern\. Allocate a structure for each TreeView item and put the string and additional data in that structure\. \(Alternatively, you could just be sneaky and have the structure be the`HTREEITEM`and the additional data\. Then you can recover the string by using the`TVM\_GETITEM`message\.\)
**Bonus chatter**: In theory, the`TVM\_SORTCHILDRENCB`could have passed the`HTREEITEM`s to the callback\. The callback could then use the`HTREEITEM`to obtain both the string and the`lParam`\. I suspect this didn’t happen because most callback functions would just ask for the`lParam`from the`HTREEITEM`,`TVM\_SORTCHILDRENCB`is doing you a favor and saving you a bunch of work by giving you the thing you probably wanted in the first place\.
### Category
### Topics
## Author

Raymond has been involved in the evolution of Windows for more than 30 years\. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie\-jeebies\. The Web site spawned a book, coincidentally also titled The Old New Thing \(Addison Wesley 2007\)\. He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information\.
This paper introduces LinTree, which improves LLM reasoning by adding explicit parent pointers to linearized search histories, showing that making the tree structure explicit boosts both task performance and search efficiency compared to implicit reasoning and heuristic-guided search.
This article demonstrates that pre-sorting random data before inserting into SQLite can improve insert performance by 2-3x, by leveraging the B+ Tree's ordered nature and reducing page splits.
A new branchless Quicksort implementation (blqsort) using sorting networks outperforms std::sort and pdqsort on Apple M1 and AMD Ryzen systems, available as single-header C and C++ libraries. It achieves speedups through branchless partitioning, median-of-medians pivot selection, and custom sorting networks for small arrays.
Introduces Amber Tree, a new syntax tree design that balances API convenience and performance between rowan's red and green trees, achieving up to 50% speedup in benchmarks.