Nancy Winnick Cluts
Microsoft Developer Network Technology Group
April 25, 1994
Revised: August 1994 (updated to reflect Windows 95 M7 changes: the ILD_OVERLAYMASK style and the ImageList_DragShow function were removed; the code now allows only four overlay masks)
December 1994 (changes: addition of ImageList_DragEnter, ImageList_DragLeave, ImageList_DrawEx, ImageList_GetIcon, and ImageList_SetDragCursorImage functions; name change of ImageList_StartDrag function to ImageList_BeginDrag; change in ImageList_Create function; addition to drawing styles in Table 1; deletion of ImageList_AddFromImageList, ImageList_CopyDitherImage, ImageList_GetImageRect, and ImageList_SetObjectOwner functions)
June 1995 (no longer a limitation on number of overlay masks)
Click to open or copy the files in the TreeView sample application for this technical article.
The next release of the Microsoft® Windows® operating system (called Windows 95) presents a new set of common controls to developers of Windows-based applications. These controls are provided in a new dynamic-link library (DLL) called COMCTL32.DLL. The controls allow developers to integrate existing applications into the new Windows 95 shell more thoroughly and seamlessly. COMCTL32.DLL is included with Windows 95 and will also be supported in Win32s® (running on Windows version 3.1) and in Windows NT™. Note that these controls are 32-bit only—they will not be supported in 16-bit Windows environments.
This article describes two new common controls: image lists and tree view controls. It is the fifth in a series of articles introducing the new common controls. The other articles in the series cover the following topics:
Parts 2–6 of the series have associated code samples that demonstrate the use of the Win32® common controls.
Warning The TreeView executable file associated with this article was built and tested using the Windows 95 Preliminary Development Kit. The executable will run only on Windows 95; it will not run under Windows 3.1 or Windows NT. If you have Windows 95 installed on your machine, but you have problems running this sample, copy the project files to your system using the button above, rebuild the project, and run the executable.
Please note that this article is based on preliminary information that is subject to change before the final version of Windows 95.
The next release of the Microsoft® Windows® operating system (called Windows 95) has implemented image lists to help you manage a collection of images of the same size, such as bitmaps or icons. You can use image lists when working with list view windows and tree view windows. A single wide bitmap contains the images within an image list. If you've worked with the toolbar in the Microsoft Foundation Class Library (MFC), you should be familiar with this type of bitmap. To reference a specific image in the bitmap, you use the index of the image within the image list. In addition to the bitmaps and icons that you normally consider images, you may also include a monochrome bitmap containing masks. These masks allow you to draw an icon transparently. You can create, destroy, add to, mask, and merge image lists.
There are two types of image lists: nonmasked and masked.
Have you ever wondered what the system uses to display the image for a shared directory—you know, the image with the hand holding a folder? It uses an overlay image. An overlay image is an image from the default image list that is drawn transparently over another image. You specify overlay images in the image list by adding the index of an image to the list of overlay masks and calling the ImageList_SetOverlayImage function. Note that the indexes for the overlay masks are one-based, not zero-based.
Creating an image list is easy: just call the ImageList_Create function. For a nonmasked image list, the function creates a single bitmap large enough to hold the specified number of images with the given dimensions. Next, it creates a screen-compatible DC and selects the bitmap into it. For a masked image list, the ImageList_Create function creates two bitmaps and two screen-compatible DCs. It selects the image bitmap into one DC and the mask bitmap into the other. Once the image list is created, its initial size is set based on the size values that you specified in your call to ImageList_Create. Adding more images than you specified automatically increases the size of the image list to accommodate the additional images by the amount, in images, that you specified your image list can grow. The CreateTreeView function that I wrote (see the "Creating a Tree View Control" section later in this article) demonstrates how to create an image list.
Now that you have a handle to your image list (provided by the call to ImageList_Create), you can add bitmapped images, icons, or cursors to the image list. The ImageList_Add function allows you to add images by passing the handles of two bitmaps. The first bitmap contains one or more images to add to the image bitmap, and the second bitmap contains the masks to add to the mask bitmap (this is NULL for nonmasked image lists).
Another way to add bitmapped images is to call the ImageList_AddMasked function. This function is similar to ImageList_Add, except that you specify a color to be combined with the image bitmap to generate the masks instead of specifying a mask bitmap. When you do this, each pixel of the specified color in the image bitmap is changed to black, and the corresponding bit in the mask is set to one. This results in transparency for any pixel in the image that matches the specified color when the image is drawn.
There are actually several more functions (specific to certain types of images such as icons or dithered images) that you can use to add images to an image list. These are explained in detail in the "Image List Functions" section later in this article.
Windows 95 provides dragging functions that enable you to move an image (masked or unmasked) smoothly and in color, as object linking and embedding (OLE) does, without any flashing of the cursor. Isn't that cool? I thought so. Dragging an object is fairly simple. You use three basic functions:
The dragging functions draw the image in the DC associated with the given window. The coordinates that specify the position of the image during a drag operation are relative to the window's upper-left corner, not the client area. This means that you must compensate for the width of window elements such as the title bar and menu bar when specifying the coordinates.
The ImageList_BeginDrag function locks all other updates to the screen, so if you need to do any drawing during a drag operation (such as highlighting the target of a drag-and-drop operation), you can use the GetDCEx function with the DCX_LOCKWINDOWUPDATE flag to get a DC that allows you to draw. In this case, you must be careful not to obliterate the dragged image. The "Drag-and-Drop Operations for a Tree View Item" section later in this article includes code that demonstrates how to do this.
Note that the dragging functions use the new image during a drag operation, so you should use the ShowCursor function to hide the actual mouse cursor after calling ImageList_BeginDrag. If you don't, the system may appear to have two mouse cursors for the duration of the drag operation. This would be bad.
By now, you've gotten used to the sections in this series containing descriptions of functions, structures, macros, groceries to buy, and so on. Well, I didn't want to disappoint anyone, so here is yet another list section on structures and macros, followed by a section that describes the image list functions. I have tried to make these sections a little more interesting by including additional details about each structure, macro, or function. If you find these sections tiresome, you have my permission to skip them entirely and move on to the section entitled "Tree View Windows." When you get to a point in your development where you need to know about a particular function or structure, come back to these sections and look it up.
Because image lists are part of the new dynamic-link library (DLL) for common controls (COMCTL32.DLL), you must include the common-control header file in your source code files and link with the common-control export library to use the image list functions, structures, and macros. It is a good idea to call the InitCommonControls function to ensure that the common-control DLL has been loaded before calling any image list function or using one of its structures.
typedef struct _IMAGEINFO {
HBITMAP hbmImage; \\ handle of the bitmap containing the images
HBITMAP hbmMask; \\ handle of the mask bitmap
int Unused; \\ not used
int Unused; \\ not used
RECT rclImage; \\ bounding rectangle of the image
} IMAGEINFO;
The IMAGEINFO structure contains information about an image in an image list. This structure is used with the ImageList_GetImageInfo function. IMAGEINFO contains the following members:
UINT INDEXTOOVERLAYMASK(UINT i)
The INDEXTOOVERLAYMASK macro prepares the one-based index of an overlay mask so the ImageList_Draw function can use it. The i parameter is the index of an overlay mask. The macro is defined as follows:
#define INDEXTOOVERLAYMASK(i) ((i) << 8)
int WINAPI ImageList_Add(HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask);
Description: The ImageList_Add function adds one or more images to an image list. You can add bitmapped images, icons, or cursors. The first bitmap contains one or more images to add to the image bitmap, and the second bitmap contains the masks to add to the mask bitmap. For nonmasked image lists, the second bitmap handle is ignored; you can set it to NULL.
Parameters:
Return value: The zero-based index of the first new image if successful; –1 otherwise.
int WINAPI ImageList_AddIcon(HIMAGELIST himl, HICON hicon);
Description: The ImageList_AddIcon function adds an icon to an image list. Since the system does not the save the hicon that is passed in, you can destroy the hicon after the function returns.
Parameters:
Return value: The zero-based index of the new image if successful; –1 otherwise.
int WINAPI ImageList_AddMasked(HIMAGELIST himl, HBITMAP hbmImage, COLORREF
crMask);
Description: The ImageList_AddMasked function adds one or more images to an image list, generating a mask from the given bitmap.
Parameters:
Return value: The zero-based index of the first new image if successful; –1 otherwise.
BOOL WINAPI ImageList_BeginDrag(HIMAGELIST himlTrack, int iTrack, int dxHotspot,
int dyHotspot);
Description: The ImageList_BeginDrag function begins dragging an image and creates a temporary image list that is used for dragging. The drag image combines the specified image and its mask with the current cursor. The drag image can be moved using the ImageList_DragMove function.
Parameters:
Return value: TRUE if successful; FALSE otherwise.
HIMAGELIST WINAPI ImageList_Create(int cx, int cy, UINT fFlags, int cInitial,
int cGrow);
Description: The ImageList_Create function creates a new image list. For a nonmasked image list, it creates a single bitmap large enough to hold the number of images.
Parameters:
ILC_MASK: The image list has a mask.
ILC_COLOR: The bit depth of the image list.
ILC_COLORDDB: Use device-dependent bitmap.
ILC_COLOR4: Use 4-bpp (bits-per-pixel) DIBSection.
ILC_COLOR8: Use 8-bpp DIBSection.
ILC_COLOR16: Use 16-bpp DIBSection.
ILC_COLOR24: Use 24-bpp DIBSection.
ILC_COLOR32: Use 32-bpp DIBSection.
ILC_PALETTE: Use palette with image list.
Return value: The handle of the image list if successful; NULL otherwise.
BOOL WINAPI ImageList_Destroy(HIMAGELIST himl);
Description: The ImageList_Destroy function destroys an image list.
Parameters: himl is the handle of the image list to destroy.
Return value: TRUE if successful; FALSE otherwise.
BOOL WINAPI ImageList_DragEnter(HWND hwndLock, int x, int y);
Description: The ImageList_DragEnter function locks the specified area of the screen from other updates. This function is called during a drag operation.
Parameters:
Return value: TRUE if successful; NULL otherwise.
BOOL WINAPI ImageList_DragLeave(HWND hwndLock);
Description: The ImageList_DragLeave function removes any locks on the lcoked area of the screen via a call to ImageList_DragEnter.
Parameters: hwndLock is the handle of the window containing the image.
Return value: TRUE if successful; NULL otherwise.
BOOL WINAPI ImageList_DragMove(int x, int y);
Description: The ImageList_DragMove function moves the drag image. This function is typically called in response to a WM_MOUSEMOVE message during a dragging operation.
Parameters: x and y represent the new drag position.
Return value: TRUE if successful; FALSE otherwise.
BOOL WINAPI ImageList_Draw(HIMAGELIST himl, int i, HDC hdcDst, int x,
int y, UINT fStyle);
Description: The ImageList_Draw function draws an image list item in the specified DC. The drawing styles listed in Table 1 below have no effect on the appearance of a nonmasked image. A nonmasked image is copied to the destination DC using the SRCCOPY raster operation. The colors in the image appear the same regardless of the background color of the DC.
Parameters:
Table 1. Image List Drawing Styles
Style | Meaning |
ILD_MASK | Draws the mask. |
ILD_IMAGE | Draws the image. |
ILD_BLEND | Blends the image with the color passed. |
ILD_BLEND25 | Blends the image with 25 percent of the color passed. |
ILD_BLEND50 | Blends the image with 50 percent of the color passed. |
ILD_FOCUS | Draws the image striped with the highlight color to indicate that it has the focus. This flag has no effect if ILD_SELECTED is not also specified or the image list does not contain a mask. |
ILD_NORMAL | Draws the image using the background color for the image list. If the background color is CLR_NONE, the image is drawn transparently using the mask. |
ILD_OVERLAYMASK | Uses these as indexes to special image items. |
ILD_SELECTED | Draws the image dithered with the highlight color to indicate that it is selected. This flag has no effect if the image list does not contain a mask. |
ILD_TRANSPARENT | Draws the image transparently using the mask, regardless of the background color. This flag has no effect if the image list does not contain a mask. The function uses a two-step process to draw the masked image. First, it performs a logical AND operation between the bits of the image and the bits of the mask. Next, it performs a logical XOR operation between the results of the first operation and the background bits of the destination DC. This creates transparent areas in the resulting image (that is, each white bit in the mask causes the corresponding bit in the resulting image to be transparent). |
BOOL WINAPI ImageList_DrawEx(HIMAGELIST himl, int i, HDC hdcDst,
int x, int y, int dx, int dy, COLORREF rgbBk, COLORREF rgbFg,
UINT fStyle);
Description: The ImageList_DrawEx function draws an image based on the flags and colors passed into the function.
Parameters:
Return value: TRUE if successful; FALSE otherwise.
HIMAGELIST WINAPI ImageList_EndDrag(VOID);
Description: The ImageList_EndDrag function ends a drag operation. Although this function returns the handle of the temporary image list that is used for dragging, the temporary image list is destroyed, so the handle returned by this function is invalid.
Parameters: None.
Return value: The handle of the temporary image list used for dragging, if successful; NULL otherwise.
HICON WINAPI ImageList_ExtractIcon(HINSTANCE hAppInst, HIMAGELIST himl, int i);
Description: The ImageList_ExtractIcon function creates an icon based on an image and mask in an image list.
Parameters:
Return value: The handle of the new icon if successful; NULL otherwise.
COLORREF WINAPI ImageList_GetBkColor(HIMAGELIST himl);
Description: The ImageList_GetBkColor function gets the current background color for an image list.
Parameters: himl is the handle of the image list.
Return value: Current background color.
HICON WINAPI ImageList_GetIcon(HIMAGELIST himl, int I, UINT flags);
Description: The ImageList_GetIcon function gets the specified icon in the image list.
Parameters:
Return value: The handle of the icon if successful; FALSE otherwise.
BOOL WINAPI ImageList_GetIconSize(IMAGELIST himl, int FAR *cx, int FAR *cy);
Description: The ImageList_GetIconSize function gets the dimensions of each image in an image list.
Parameters:
Return value: TRUE if successful; FALSE otherwise.
int WINAPI ImageList_GetImageCount(HIMAGELIST himl);
Description: The ImageList_GetImageCount function gets the number of images in an image list.
Parameters: himl is the handle of the image list.
Return value: The number of images in the list.
BOOL WINAPI ImageList_GetImageInfo(HIMAGELIST himl, int i, IMAGEINFO FAR*
pImageInfo);
Description: The ImageList_GetImageInfo function gets information about an image and fills an IMAGEINFO structure with information about a single image. You can use this information to manipulate the bitmaps for the image directly.
Parameters:
Return value: TRUE if successful; FALSE otherwise.
HIMAGELIST WINAPI ImageList_LoadBitmap(HINSTANCE hi, LPCSTR lpbmp, int cx,
int cGrow, COLORREF crMask);
Description: The ImageList_LoadBitmap function creates an image list from the given bitmap resource.
Parameters:
Return value: The handle of the image list if successful; NULL otherwise.
HIMAGELIST WINAPI ImageList_Merge(HIMAGELIST himl1, int i1, HIMAGELIST himl2,
int i2, int dx, int dy);
Description: The ImageList_Merge function merges two existing images, creating a new image list to store the image. The second image is drawn transparently over the first image, and the mask for the new image is the result of performing a logical OR operation between the masks for the two images.
Parameters:
Return value: The handle of the new image list if successful; NULL otherwise.
BOOL WINAPI ImageList_Remove(HIMAGELIST himl, int i);
Description: The ImageList_Remove function removes an image from an image list.
Parameters:
Return value: TRUE if successful; FALSE otherwise.
BOOL WINAPI ImageList_Replace(HIMAGELIST himl, int i, HBITMAP hbmImage,
HBITMAP hbmMask);
Description: The ImageList_Replace function replaces an image in an image list.
Parameters:
Return value: TRUE if successful; FALSE otherwise.
int WINAPI ImageList_ReplaceIcon(HIMAGELIST himl, int i, HICON hicon);
Description: The ImageList_ReplaceIcon function replaces an image in an image list, using an icon.
Parameters:
Return value: The index of the image if successful; –1 otherwise.
COLORREF WINAPI ImageList_SetBkColor(HIMAGELIST himl, COLORREF clrBk);
Description: The ImageList_SetBkColor function sets the background color for an image list.
Parameters:
Return value: The previous background color if successful; CLR_NONE otherwise.
BOOL WINAPI ImageList_SetDragCursorImage(HIMAGELIST himlDrag,
int iDrag, int dxHotSpot, int dyHotSpot);
Description: The ImageList_SetDragCursorImage function sets the image of the dragged item.
Parameters:
Return value: TRUE if successful; NULL otherwise.
BOOL WINAPI ImageList_SetOverlayImage(HIMAGELIST himl, int iImage,
int iOverlay);
Description: The ImageList_SetOverlayImage function adds the index of an image to the list of images to be used as overlay masks. The index must be specified using the INDEXTOOVERLAYMASK macro described above.
Parameters:
Return value: TRUE if successful; FALSE otherwise.
You thought that you would never see
A built-in control that supported a tree
Like that one? Have you heard this one:
There was a programmer named Dale
Whose knees were exceedingly pale.
He used MFC,
OLE 2, and VB
To write great new code that won't fail.
Well, Dale and many other developers suggested that we support tree structures in the Windows operating environment, so we decided to include them in Windows 95.
The tree view control gives you a way to display a hierarchical list of items. Each item has a label and can optionally have a bitmap associated with it. You've seen these hierarchies before in File Manager (displaying directory information) and in Microsoft Mail (displaying mail folders). The top item in the hierarchy is called the root item. The root item has no parent. An item that is below the root item in the hierarchy is called a child item of the root. An item that has child items is called a parent item. Child items are displayed in indented form below their parent item. The items can be connected by lines if you specify the TVS_HASLINES style. Figure 1 shows a tree view window that lists houses for sale in various cities in the beautiful Pacific Northwest. (The addresses are fictional—the houses really aren't for sale.)
Figure 1. Anatomy of a tree view window
You can use four styles to control the appearance and behavior of a tree view window. These styles are initially set when you create the tree view by calling the CreateWindow or CreateWindowEx function. You can query and change the styles later by using the GetWindowLong and SetWindowLong functions. Table 2 below lists the currently supported window styles that are unique to tree view windows.
Table 2. Tree View Window Styles
Style | Description |
TVS_EDITLABELS | Allows the user to edit the labels of list view items. |
TVS_HASBUTTONS | Displays plus (+) and minus (–) buttons next to parent items to expand or collapse the parent item's list of child items. This style does not add buttons to items at the root of the hierarchy. To do that, combine the TVS_HASLINES, TVS_LINESATROOT, and TVS_HASBUTTONS styles. |
TVS_HASLINES | Uses lines to show the hierarchy of items. The lines are drawn to link the parent and child items. This style does not link items at the root of the hierarchy. |
TVS_LINESATROOT | Uses lines to link items at the root of the list view. |
A tree view window allocates memory for storing each item in a tree. Having the tree view allocate memory for an item's label can take up quite a bit of memory. If your application is already maintaining a copy of the strings, you may want to avoid this extra allocation. Instead, you can specify that a callback function (LPSTR_TEXTCALLBACK) be used whenever the tree view window needs some text. A TVN_GETDISPINFO notification is then sent to the parent window with the address of a TV_DISPINFO structure. The parent fills in the text for the label when it receives this notification.
You can allow a user to edit item labels directly in a tree view window by specifying the TVS_EDITLABELS style when creating the tree view window. When the user clicks the label of an item that has the focus, you can assume that label editing should begin. An application sends a TVM_EDITLABEL message to the tree view window to begin editing. The tree view window then notifies the parent window that editing has begun by sending the TVN_BEGINLABLEEDIT notification. When label editing is complete or has been cancelled, a TVN_ENDLABLEEDIT notification is sent to the parent window, and the parent window updates the item's label. You can allow the user to edit some labels and prevent the user from editing others by processing the TVN_BEGINLABELEDIT notification and returning zero to allow editing, or a nonzero value to prevent editing. When label editing is cancelled or completed, the lParam parameter is the address of a TV_DISPINFO structure that identifies the item being edited and the edited text. The item value is –1 if editing was cancelled.
During label editing, you can get the handle of the edit control by using the TVM_GETEDITCONTROL message. This way, you can limit the amount of text the user can enter (EM_LIMITTEXT) and you can even subclass the edit control to do some dynamic data validation. Since the edit control is created after the TVN_BEGINLABELEDIT notification is sent, you will need to wait until the notification is sent before attempting to get the handle to the edit control.
Each item in a tree view control can have a pair of bitmaps that appear on the left side of its label. One bitmap is displayed when the item is selected, and the other is displayed when the item is not selected. To use item bitmaps, you must create an image list, add the bitmaps to it, and associate the image list with the tree view control by using the TVM_SETIMAGELIST message. By default, all items display the first image in the image list as both the selected and nonselected bitmaps. You can change this behavior for a particular item by specifying the indexes of the selected and nonselected images when adding the item to the tree view with the TVM_INSERTITEM message.
Each item in a tree view control has a current state indicating, for example, whether the item is selected, disabled, or expanded. Most of the time, some type of user action sets the state. For example, when a user clicks an item, the state is set to "selected" in response to the action. However, the item state can also be set programmatically by sending the TVM_SETITEM message or using its corresponding TreeView_SetItem macro. Table 3 lists the currently supported states for tree view items.
Table 3. Tree View Item States
Item State | Meaning |
TVIS_CUT | The item is marked. |
TVIS_DISABLED | The item is disabled and is drawn using the standard disabled style and color. |
TVIS_DROPHILITED | The item is highlighted as a drag-and-drop target. |
TVIS_EXPANDED | The item's list of child items is currently expanded. |
TVIS_EXPANDEDONCE | The item's list of child items has been expanded at least once. |
TVIS_FOCUSED | The item has the focus and is drawn with the standard focus rectangle. |
TVIS_OVERLAYMASK | An overlay image is used as a mask with the item image. |
TVIS_SELECTED | The item is selected. |
TVIS_USERMASK | A user-defined mask is set. If you set the image to be a state image list, this mask will specify the indexes into the state image list and draw another image next to the normal item image. For example, you can use this state to put a check mark next to a tree view item image. |
At any given time, the parent item can be either expanded or collapsed. When a parent item is expanded, the child items are displayed and indented below the parent item. You can set the indentation programmatically by sending the TVM_SETINDENT message. When a parent item is in the collapsed state, the child items are not displayed. When a user double-clicks a parent item or the plus (+) button next to a parent item, the state of the parent item toggles between expanded and collapsed. An application can expand or collapse the parent item programmatically by using the TVM_EXPAND message. A TVN_ITEMEXPANDING notification is then sent. Trapping this notification allows you to prevent the change, or set any attributes of the parent item that depend on the expanded or collapsed state. After changing the state of the parent, the tree view sends the parent window a TVN_ITEMEXPANDED notification.
Table 4 contains the list of notifications that are sent to the parent window of a tree view control. lParam sent along with the notification contains a pointer to an NM_TREEVIEW structure for all notifications except TV_GETDISPINFO and TVN_SETDISPINFO. These notifications pass a TV_DISPINFO structure in lParam.
Table 4. Tree View Notification Messages
Message | Description |
TVN_BEGINDRAG | A drag-and-drop operation has begun. |
TVN_BEGINLABELEDIT | In-place label editing has begun. |
TVN_BEGINRDRAG | A drag-and-drop operation using the right mouse button has begun. |
TVN_DELETEITEM | An item has been deleted. |
TVN_ENDLABELEDIT | Label editing has ended. |
TVN_GETDISPINFO | The tree view control needs information (such as item text) to display an item. |
TVN_ITEMEXPANDED | A parent item's list of child items was expanded or collapsed. |
TVN_ITEMEXPANDING | A parent item's list of child items is about to be expanded or collapsed. |
TVN_KEYDOWN | A keyboard event has occurred. |
TVN_SELCHANGED | The item selection has changed. The .action member of the NM_TREEVIEW structure can be one of the following: TVC_UNKNOWN (unknown reason), TVC_BYMOUSE (the selection changed due to a mouse click), or TVC_BYKEYBOARD (the selection changed due to a keyboard event). |
TVN_SELCHANGING | The item selection is about to change. See TVN_SELCHANGED above for more information. |
TVN_SETDISPINFO | The parent window must update the item information. |
To create a tree view control, use the CreateWindow or CreateWindowEx function, and specify the WC_TREEVIEW style for the window class. Remember that the tree view window class is part of the new DLL for common controls (COMCTL32.DLL), so you should call the InitCommonControls function to ensure that COMCTL32.DLL has been loaded. The following example creates a tree view control that is sized to fit the client area of the parent window. It uses the image list functions to create an image list that it associates with the tree view.
HWND CreateTreeView (HWND hWndParent)
{
HWND hwndTree; // The handle to the tree view window.
RECT rcl; // A rectangle for setting the size of the window.
HBITMAP hBmp; // The handle to a bitmap.
HIMAGELIST hIml; // The handle to the image list.
// Ensure that the common-control DLL is loaded.
InitCommonControls();
// Get the size and position of the parent window.
GetClientRect(hWndParent, &rcl);
// Create the tree view window.
hwndTree = CreateWindowEx( 0L,
WC_TREEVIEW,
"",
WS_VISIBLE | WS_CHILD | WS_BORDER | TVS_HASLINES | TVS_HASBUTTONS |
TVS_LINESATROOT,
0, 0,
rcl.right - rcl.left, rcl.bottom - rcl.top,
hWndParent,
(HMENU) ID_TREEVIEW,
hInst,
NULL );
if (hwndTree == NULL )
return NULL;
// Initialize the tree view window.
// First, create the image list we will need.
hIml = ImageList_Create( BITMAP_WIDTH, BITMAP_HEIGHT,
FALSE, NUM_BITMAPS, 0 );
// Load the bitmaps and add them to the image lists.
hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(FORSALE));
idxForSale = ImageList_Add(hIml, hBmp, NULL);
hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(REDMOND));
idxRedmond = ImageList_Add(hIml, hBmp, NULL);
hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(BELLEVUE));
idxBellevue = ImageList_Add(hIml, hBmp, NULL);
hBmp = LoadBitmap(hInst, MAKEINTRESOURCE(SEATTLE));
idxSeattle = ImageList_Add(hIml, hBmp, NULL);
// Make sure that all of the bitmaps were added.
if (ImageList_GetImageCount(hIml) < NUM_BITMAPS)
return FALSE;
// Associate the image list with the tree.
TreeView_SetImageList(hwndTree, hIml, idxForSale);
return (hwndTree);
}
Now that our tree view window has been created, it is time to add items to it. You can add items to a tree view by sending the TVM_INSERTITEM message or by calling the associated TreeView_InsertItem macro. For each item that you want to insert, you fill out the TV_ITEM and TV_INSERTSTRUCT structures. When adding an item, you must specify the handle of the new item's parent item. If you specify NULL or TVI_ROOT instead of an item handle, the item is added as a root item.
The example below demonstrates how to add items to a tree view window. This sample handles a real-estate listing for three cities, with three houses listed for each city. A global structure keeps track of the handle to the parent item and its image.
typedef struct tagHOUSEINFO {
char szAddress[MAX_ADDRESS];
int iImage;
HTREEITEM hParent;
}
BOOL AddTreeViewItems( HWND hwndTree )
{
static HTREEITEM hTRoot, hTRed, hTBel, hTSea, hPrev;
char szText[MAX_LEN];
int index;
// First, add the root item "Houses for Sale".
LoadString(hInst, IDS_FORSALE, szText, MAX_LEN);
hTRoot = AddOneItem((HTREEITEM)NULL, szText, (HTREEITEM)TVI_ROOT, idxForSale,
hwndTree);
// Now add the cities.
LoadString(hInst, IDS_REDMOND, szText, MAX_LEN);
hTRed = AddOneItem(hTRoot, szText, (HTREEITEM)TVI_FIRST, idxRedmond,
hwndTree);
LoadString(hInst, IDS_BELLEVUE, szText, MAX_LEN);
hTBel = AddOneItem(hTRoot, szText, hTRed, idxBellevue, hwndTree);
LoadString(hInst, IDS_SEATTLE, szText, MAX_LEN);
hTSea = AddOneItem(hTRoot, szText, hTBel, idxSeattle, hwndTree);
// Fill in the structure for each house.
FillInStruct(hTRed, idxRedmond, 0, 3);
FillInStruct(hTBel, idxBellevue, 3, 6);
FillInStruct(hTSea, idxSeattle, 6, 9);
// Add the houses for each city.
hPrev = hTSea;
for (index = 0; index < NUM_HOUSES; index++)
hPrev = AddOneItem(rgHouseInfo[index].hParent,
rgHouseInfo[index].szAddress,
hPrev,
rgHouseInfo[index].iImage,
hwndTree);
return TRUE;
}
// This function saves the current image and handle to the
// parent of the tree view item.
VOID FillInStruct(HTREEITEM hParent, int iImage, int index, int iMax)
{
for (;index < iMax; index++)
{
rgHouseInfo[index].iImage = iImage;
rgHouseInfo[index].hParent = hParent;
}
}
// This function fills in the TV_ITEM and TV_INSERTSTRUCT structures and
// adds the item to the tree view.
HTREEITEM AddOneItem( HTREEITEM hParent, LPSTR szText, HTREEITEM hInsAfter,
int iImage, HWND hwndTree)
{
HTREEITEM hItem;
TV_ITEM tvI;
TV_INSERTSTRUCT tvIns;
// The .pszText, .iImage, and .iSelectedImage are filled in.
tvI.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
tvI.pszText = szText;
tvI.cchTextMax = lstrlen(szText);
tvI.iImage = iImage;
tvI.iSelectedImage = iImage;
tvIns.item = tvI;
tvIns.hInsertAfter = hInsAfter;
tvIns.hParent = hParent;
// Insert the item into the tree.
hItem = (HTREEITEM)SendMessage(hwndTree, TVM_INSERTITEM, 0,
(LPARAM)(LPTV_INSERTSTRUCT)&tvIns);
return (hItem);
}
Now that you have a tree view that can be expanded and collapsed, you may be thinking how neat it would be if the user could just pick up one of the items and drag it to a new location. The tree view window has some built-in functions that facilitate dragging and dropping of tree view items. When processing the drag operation for a tree view item, an application typically does three things:
The following example demonstrates how to handle a simple drag-and-drop operation in a tree view window.
case WM_NOTIFY:
switch( ((LPNMHDR)lParam)->code)
{
case TVN_BEGINDRAG:
// The user wants to drag an item. Call the drag handler.
BeginDrag(hWndTreeView, (NM_TREEVIEW *)lParam);
// Save off the dragged item information.
tvI = ((NM_TREEVIEW *)lParam)->iItemNew;
break;
default:
break;
}
break;
case WM_MOUSEMOVE:
// If dragging, move the image.
if (g_fDragging)
{
// Drag the item to the current mouse position.
ImageList_DragMove(LOWORD(lParam),HIWORD(lParam));
// If the cursor is on an item, highlight it as the drop target.
tvHit.pt.x = LOWORD(lParam);
tvHit.pt.y = HIWORD(lParam);
if ((hTarget = TreeView_HitTest(hWndTreeView, &tvHit)) != NULL)
{
TreeView_SelectDropTarget(hWndTreeView, hTarget);
}
}
break;
case WM_LBUTTONUP:
// If dragging, stop it.
if (g_fDragging)
{
// Process item drop.
DropItem(hDragItem, hWndTreeView);
// Inform image list that dragging has stopped.
ImageList_EndDrag();
// Release the mouse capture.
ReleaseCapture();
// Show the cursor.
ShowCursor(TRUE);
// Reset the global Boolean flag to a non-dragging state.
g_fDragging = FALSE;
}
break;
.
.
.
VOID BeginDrag(HWND hwndTree, NM_TREEVIEW *lItem)
{
HIMAGELIST hIml;
RECT rcl;
DWORD dwLevel;
DWORD dwIndent;
// Create an image to use for dragging.
hIml = TreeView_CreateDragImage(hwndTree, lItem->itemNew.hItem);
// Get the bounding rectangle of the item being dragged.
TreeView_GetItemRect(hwndTree, lItem->itemNew.hItem, &rcl, TRUE);
// Start dragging the image.
ImageList_BeginDrag(hIml, 0, lItem->ptDrag.x, lItem->ptDrag.y);
// Show the cursor.
ShowCursor(FALSE);
// Capture the mouse.
SetCapture(GetParent(hwndTree));
// Set a global flag that tells whether dragging is happening.
g_fDragging = TRUE;
}
// Function that processes the item drop.
VOID DropItem(HTREEITEM hDragItem, HWND hwnd)
{
HTREEITEM hParent, hNewItem, hTarget;
TV_ITEM tvTarget;
int index;
// Get the handle to the drop target.
hTarget = TreeView_GetDropHilight(hwnd);
// Get the parent of the drop target.
hParent = TreeView_GetParent(hwnd, hTarget);
// Get the image information.
tvTarget.hItem = hTarget;
tvTarget.mask = TVIF_IMAGE;
TreeView_GetItem(hwnd, &tvTarget);
// Get the index into the structure maintained containing
// the text for the items.
for (index = 0; index < NUM_HOUSES; index++)
{
if (rgHouseInfo[index].hItem == hDragItem)
break;
}
if (index == NUM_HOUSES)
index--;
// Insert the new item back in.
hNewItem = AddOneItem( hParent, rgHouseInfo[index].szAddress, hTarget,
tvTarget.iImage, hwnd);
// Delete the "dragged" item.
TreeView_DeleteItem(hwnd, hDragItem);
// Reset the drop target to NULL.
TreeView_SelectDropTarget(hwnd, (HTREEITEM)NULL);
}
This section describes the structures that are unique to tree view windows. If you have been following this series of articles closely, you will know that this is one of the sections that you can skip if you really hate to read lists. So go ahead. Skip this section. See if it hurts my feelings. Don't even think about how much time and effort it took me to write this.
typedef struct _NM_TREEVIEW {
NMHDR hdr; \\ common control notification structure
UINT action; \\ notification-specific action flag
TV_ITEM itemOld; \\ old item state
TV_ITEM itemNew; \\ new item state
POINT ptDrag; \\ location where event occurred
} NM_TREEVIEW;
The NM_TREEVIEW structure contains information about a tree view notification. The address of this structure is specified as the lParam parameter of the WM_NOTIFY message for several tree view notifications. The structure includes the following members:
typedef struct _TV_DISPINFO {
NMHDR hdr; \\ common control notification structure
TV_ITEM item; \\ tree view item information
} TV_DISPINFO;
The TV_DISPINFO structure contains information about the display of tree view items. The structure includes the following members:
typedef struct _TV_HITTESTINFO {
POINT pt; \\ coordinates of point to test
UINT flags; \\ receives hit test information
HTREEITEM hitem; \\ item that occupies the hit point
} TV_HITTESTINFO;
The TV_HITTESTINFO structure contains information used to determine the location of a point relative to a tree view control. This structure is used with the TVM_HITTEST message. TV_HITTESTINFO includes the following members:
TVHT_ABOVE: Above the client area.
TVHT_BELOW: Below the client area.
TVHT_NOWHERE: In the client area, but below the last item.
TVHT_ONITEM: On the bitmap or label associated with an item.
TVHT_ONITEMBUTTON: On the button associated with an item.
TVHT_ONITEMICON: On the bitmap associated with an item.
TVHT_ONITEMINDENT: In the indentation associated with an item.
TVHT_ONITEMLABEL: On the text label associated with an item.
TVHT_ONITEMRIGHT: In the area to the right of an item.
TVHT_ONITEMSTATEICON: On the state image icon.
TVHT_TOLEFT: To the right of the client area.
TVHT_TORIGHT: To the left of the client area.
typedef struct _TV_INSERTSTRUCT {
HTREEITEM hParent; \\ handle of the parent item
HTREEITEM hInsertAfter; \\ handle of item after which to insert this item
TV_ITEM item; \\ item to insert
} TV_INSERTSTRUCT;
The TV_INSERTSTRUCT structure contains information used to add a new item to a tree view control. This structure is used with the TVM_INSERTITEM message. TV_INSERTSTRUCT includes the following members:
TVI_ROOT: Inserts the item at the root of the tree.
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 into the list in alphabetical order.
typedef struct _TV_ITEM {
UINT mask; \\ specifies which members are valid
HTREEITEM hItem; \\ the item that this structure refers to
UINT state; \\ current state of the item
UINT stateMask; \\ current state of the item mask
LPSTR pszText; \\ text for the item
int cchTextMax; \\ size of the buffer containing the item text
int iImage; \\ index of the image for this item
int iSelectedImage; \\ index of the selected image
int cChildren; \\ number of child nodes
LPARAM lParam; \\ application-defined item data
} TV_ITEM;
The TV_ITEM structure contains the attributes of a tree view item. When this structure is used in conjunction with a function or message that gets item information, only the structure members specified in the mask member contain valid data, and all other members are invalid. When this structure is used in conjunction with a function that sets item information, the mask member specifies which of the attributes are valid and should be set. The TV_ITEM structure includes the following members:
TVIF_CHILDREN: The cChildren member is valid.
TVIF_HANDLE: The hItem member is valid.
TVIF_IMAGE: The iImage member is valid.
TVIF_PARAM: The lParam member is valid.
TVIF_SELECTEDIMAGE: The iSelectedImage member is valid.
TVIF_STATE: The state and stateMask members are valid.
TVIF_TEXT: The pszText an cchTextMax members are valid.
typedef struct _TV_KEYDOWN {
NMHDR hdr; \\ common control notification structure
WORD wVKey; \\ virtual key code
UINT flags; \\ not used; always set to zero
} TV_KEYDOWN;
The TV_KEYDOWN structure contains information about a keyboard event in a tree view control. This structure is used with the TVN_KEYDOWN notification. TV_KEYDOWN includes the following members:
typedef struct _TV_SORTCB {
HTREEITEM hParent; \\ handle of the parent item
PFNTVCOMPARE lpfnCompare; \\ comparison function
LPARAM lParam; \\ application-defined sort data
The TV_SORTCB structure contains information for sorting child items in a tree view control. The TVM_SORTCHILDRENCB message uses this structure. The comparison function must return a negative value if the first item should precede the second, a positive value if the first item should follow the second, or zero if the two items are equivalent. The lParam1 and lParam2 parameters correspond to the lParam member of the TV_ITEM structure for the two items being compared. The lParamSort parameter corresponds to the lParam member of the TV_SORTCB structure that was passed with the TVM_SORTCHILDRENCB message. The comparison function has the following form:
int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
The TV_SORTCB structure includes the following members:
An application sends messages to add items and to control the appearance and behavior of a tree view window. Each message has a corresponding macro that you can use instead of sending the message explicitly. This section describes the messages that Windows 95 currently supports for tree view windows.
wParam = 0; \\ not used
lParam = (HTREEITEM)hitem; \\ handle of the tree view item
Description: The TVM_CREATEDRAGIMAGE message creates a dragging bitmap for the given item in a tree view.
Parameters: wParam is not used. lParam (HTREEITEM hitem) is the handle of the tree view item for which a dragging bitmap will be created.
Return value: The handle of the image list to which the dragging bitmap was added (HIMAGELIST) if successful; otherwise NULL.
Macro: HIMAGELIST TreeView_CreateDragImage(hwnd, hitem);
wParam = 0; \\ not used
lParam = (HTREEITEM)hitem; \\ handle of the tree view item
Description: The TVM_DELETEITEM message deletes a specified item from a tree view window. This message has two macros, TreeView_DeleteItem and TreeView_DeleteAllItems, which you can use to delete either one item or all of the items from a tree view window. If the item label is being edited when this message is sent, the edit operation is cancelled and the parent window receives a TVN_ENDLABELEDIT notification. After that notification, a TVN_DELEITEM notification is sent to the parent window. If hitem is TVI_ROOT, all of the items are deleted from the control.
Parameters: wParam is not used. lParam (HTREEITEM hitem) is the handle of the tree view item to be deleted.
Return value: TRUE if successful; FALSE otherwise.
Macros:
wParam = 0; \\ not used
lParam = (HTREEITEM)hitem; \\ handle of the tree view item
Description: The TVM_EDITLABEL message begins in-place editing of the specified item's text. The item text is replaced by a single-line edit control containing the original text in a selected and focused state. A TVN_BEGINLABELEDIT notification is sent to the parent window of the tree view control. You can safely subclass the edit control, but you must not destroy it. When the user has finished editing the label or has cancelled, the handle to the edit window becomes invalid.
Parameters: wParam is not used. lParam (HTREEITEM hitem) is the handle of the tree view item whose text will be edited.
Return value: The handle of the edit control used to edit the item text if successful; NULL otherwise.
Macro: HWND TreeView_EditLabel(hwnd, hitem);
wParam = 0; \\ not used
lParam = (HTREEITEM)hitem; \\ handle of the tree view item
Description: The TVM_ENSUREVISIBLE message ensures that the tree view item is visible, and expands the parent item or scrolls the tree view window if necessary. If the message expands the parent item, TVN_ITEMEXPANDING and TVN_ITEMEXPANDED notifications will be sent to the parent window of the tree view window.
Parameters: wParam is not used. lParam (HTREEITEM hitem) is the handle of the tree view item to be checked for visibility.
Return value: TRUE if successful; FALSE otherwise.
Macro: BOOL TreeView_EnsureVisible(hwnd, hitem);
wParam = (UINT)code; \\ the action to take place
lParam = (HTREEITEM)hitem; \\ handle of the tree view item
Description: The TVM_EXPAND message expands or collapses the list of child items associated with the specified parent item. This message sends TVN_ITEMEXPANDING and TVN_ITEMEXPANDED notifications to the parent window.
Parameters: lParam (HTREEITEM hitem) is the handle of the parent item to be expanded or collapsed. wParam (WPARAM UNIT code) identifies the action to take place. This can be one of the following values:
Return value: TRUE if anything changed; FALSE otherwise.
Macro: BOOL TreeView_Expand(hwnd, hitem, code);
wParam = 0; \\ not used
lParam = 0; \\ not used
Description: The TVM_GETCOUNT message returns the number of items in the tree view window.
Parameters: wParam and lParam are not used.
Return value: The number of items in the tree view window.
Macro: UINT TreeView_GetCount(hwnd);
wParam = 0; \\ not used
lParam = 0; \\ not used
Description: The TVM_GETEDITCONTROL message gets the handle of the edit control being used for in-place item text editing.
Parameters: wParam and lParam are not used.
Return value: The handle to the edit control.
Macro: HWND TreeView_GetEditControl(hwnd);
wParam = iImage; \\ index of the tree item
lParam = 0; \\ not used
Description: The TVM_GETIMAGELIST message gets the handle of the image list associated with the tree view window.
Parameters: wParam is the index of the tree item. lParam is not used.
Return value: The handle to the image list.
Macro: HIMAGELIST TreeView_GetImageList(hwnd, iImage);
wParam = 0; \\ not used
lParam = 0; \\ not used
Description: The TVM_GETINDENT message gets the amount, in pixels, that child items are indented relative to their parent items.
Parameters: wParam and lParam are not used.
Return value: The amount of indentation.
Macro: UINT TreeView_GetIndent(hwnd);
wParam = 0; \\ not used
lParam = (TV_ITEM FAR *)pitem; \\ structure that receives item information
Description: The TVM_GETITEM message gets information about the specified tree view item depending on the mask member in the TV_ITEM structure passed in.
Parameters: wParam is not used. lParam (TV_ITEM FAR *pitem) is a pointer to the TV_ITEM structure to fill in.
Return value: TRUE if successful; FALSE otherwise.
Macro: BOOL TreeView_GetItem(hwnd, pitem);
wParam = code; \\ visibility state of the item
lParam = (RECT FAR *)prc; \\ bounding rectangle of the item
Description: The TVM_GETITEMRECT message gets the bounding rectangle and visibility state of the specified item.
Parameters: wParam (WPARAM code) is the visibility state of the item (TRUE for shown, FALSE for hidden). lParam (LPARAM RECT FAR * prc) is the bounding rectangle of the item.
Return value: TRUE if visible; otherwise, returns FALSE and does not fill in the rectangle.
Macro: BOOL TreeView_GetItemRect(hwnd, hitem, prc, code);
wParam = (UINT)code; \\ which item to retrieve
lParam = (HTREEITEM)hitem; \\ handle of the tree view item
Description: The TVM_GETNEXTITEM message gets the next tree view item based on the specified code. You can use macros instead of sending this message explicitly. There is one macro for each code you can specify and one general-purpose macro that allows you to specify the code. Table 5 below lists the possible codes and their meanings.
Parameters: wParam (WPARAM UINT code) identifies the item to retrieve. lParam (HTREEITEM hitem) is the handle of the tree view item.
Return value: The handle of the item if successful; NULL otherwise.
Macros:
Table 5. Tree View Get Item Codes
Code | Meaning |
TVGN_CARET | Gets the currently selected item. |
TVGN_CHILD | Gets the first child item. |
TVGN_DROPHILITE | Gets the item that is the target of a drag-and-drop operation. |
TVGN_FIRSTVISIBLE | Gets the first visible item. |
TVGN_NEXT | Gets the next sibling item. |
TVGN_NEXTVISIBLE | Gets the next visible item. |
TVGN_PARENT | Gets the parent of the item. |
TVGN_PREVIOUS | Gets the previous item. |
TVGN_PREVIOUSVISIBLE | Gets the first visible item that precedes the given item. |
TVGN_ROOT | Gets the first child item of the root item. |
wParam = 0; \\ not used
lParam = 0; \\ not used
Description: The TVM_GETVISIBLECOUNT message gets the count of items that will fit into the client window of the tree window.
Parameters: wParam and lParam are not used.
Return value: The count of items.
Macro: UINT TreeView_GetVisibleCount(hwnd);
wParam = 0; \\ not used
lParam = (LPTV_HITTESTINFO)lpht; \\ the point to hit test
Description: The TVM_HITTEST message gets the point relative to the client area of the tree view window of the specified point. This message is generally used for drag-and-drop operations.
Parameters: wParam is not used. lParam (LPARAM LPTV_HITTESTINFO lpht) is the point to hit test.
Return value: The handle of the tree view item that is occupying the specified point, or NULL if no items occupy the point.
Macro: HTREEITEM TreeView_HitTest(hwnd, lpht);
wParam = 0; \\ not used
lParam = (LPTV_INSERTSTRUCT)lpis; \\ structure containing item attributes
Description: The TVM_INSERTITEM message inserts a new item in a tree view window. If the item is being edited, the edit operation is cancelled and the parent window receives a TVN_ENDLABELEDIT notification.
Parameters: wParam is not used. lParam (LPARAM LPTV_INSERTSTRUCT lpis) is the address of a TV_INSERTSTRUCT structure specifying the attributes of the tree view item.
Return value: The handle of the new item if successful; NULL otherwise.
Macro: HTREEITEM TreeView_InsertItem(hwnd, lpis);
wParam = code; \\ how to select the item
lParam = (HTREEITEM)hitem; \\ handle of the tree view item
Description: The TVM_SELECTITEM message selects the given tree view item, scrolls it into view, and redraws it. This message has three corresponding macros described below.
Parameters: lParam (HTREEITEM hitem) is the handle of the tree view item to redraw. wParam (WPARAM code) identifies the action the selection should take:
Return value: TRUE if successful; FALSE otherwise.
Macros:
wParam = iImage; \\ new image list
lParam = (HIMAGELIST)himl; \\ handle of the image list
Description: The TVM_SETIMAGELIST message sets the image list for a tree view window and redraws it.
Parameters: wParam (int iImage) is the new image list. lParam (LPARAM HIMAGELIST himl) is the handle of the image list. If NULL is passed, all of the images are removed from the tree view window.
Return value: Handle of the previous image list if successful; NULL otherwise.
Macro: HIMAGELIST TreeView_SetImageList(hwnd, himl, iImage);
wParam = indent; \\ amount of indentation in pixels
lParam = 0; \\ not used
Description: The TVM_SETINDENT message sets the amount of indentation for a child item.
Parameters: wParam (WPARAM indent) is the amount, in pixels, of indentation. There is a system-defined minimum indentation (five). If indent is less than this value, the new width will be the system-defined minimum. lParam is not used.
Return value: None.
Macro: BOOL TreeView_SetIndent(hwnd, indent);
wParam = 0; \\ not used
lParam = (const TV_ITEM FAR *)pitem; \\ item attributes to set
Description: The TVM_SETITEM message sets the attributes of a tree view item based on the mask member of the TV_ITEM structure passed in.
Parameters: wParam is not used. lParam (LPARAM const TV_ITEM FAR * pitem) identifies the item attributes to set.
Return value: 0 if successful; –1 otherwise.
Macro: BOOL TreeView_SetItem(hwnd, pitem);
wParam = (BOOL)fRecurse; \\ TRUE to sort recursively
lParam = (HTREEITEM)hitem; \\ handle of the tree view item
Description: The TVM_SORTCHILDREN message sorts the child items of the given parent item.
Parameters: If wParam (WPARAM fRecurse) is TRUE, all levels of child items descending from the given parent item are sorted. Otherwise, only immediate child items are sorted. lParam (HTREEITEM hitem) is the handle of the parent tree view item.
Return value: TRUE if successful; FALSE otherwise.
Macro: BOOL TreeView_SortChildren(hwnd, hitem, fRecurse);
wParam = (BOOL)fRecurse; \\ TRUE to sort recursively
lParam = (LPTV_SORTCB)psort; \\ address of a TV_SORTCB structure
Description: The TVM_SORTCHILDRENCB message sorts tree view items using an application-defined comparison function.
Parameters: If wParam (WPARAM fRecurse) is TRUE, all levels of child items descending from the given parent item are sorted. Otherwise, only immediate child items are sorted. lParam (LPARAM LPTV_SORTCB psort) is the address of a TV_SORTCB structure specifying the address of the application-defined comparison function. This function is called during the sort operation whenever the relative order of two list items needs to be compared.
Return value: TRUE if successful; FALSE otherwise.
Macro: BOOL TreeView_SortChildrenCB(hwnd, psort, fRecurse);
Here we are, once again, at the end of yet another article in the Win32 common control series. My final article (Part 6 of the series) covers the new tab controls and property sheets. Although property sheets are not part of the common control library, tab controls are. Since tabs are used extensively with property sheets, I decided to add information about property sheets as an extra bonus for you. Stay tuned for upcoming Windows 95 articles in the MSDN Library: Same Bat Time, Same Bat Channel.