Initializing And Handling The Walk Registry Tree Page

The Walk Registry Tree page is by far the most involved of the problems we tackle in the RapiDemo example. The reason for this is that the Walk Registry Tree page makes use of the highly sophisticated MFC control, CTreeCtrl. Tree controls aren’t easy to code, but they are very powerful tools for depicting hierarchies of variable structure and depth. File systems, databases, and the Windows Registry are all examples of such hierarchies.

In the CWalkReg class, we take an in depth look at how to use CTreeCtrl to display the Windows CE Registry.

How The “Walk Registry Tree” Page Uses the MFC Tree Control

The natural choice for displaying hierarchically organized data is the MFC Tree Control. To use a tree control, we have to do three things:

  • Discern hierarchical relationships among tree items.
  • Add items to the tree control, by initializing the TVITEM structure with information that defines the appearance of the item and its relationship to neighboring tree items.
  • Handle tree control notification messages.

First, we’ll see how to add a single item to the tree control, and then we’ll see how to handle tree control notifications. Finally, we’ll tie the concepts together by “walking” out the Registry tree, adding tree items hierarchically. The Walk Registry Tree page is implemented in the classCWalkReg, which creates and initializes the tree control when the page is created, and which handles notification messages from the tree control.

Adding A Single Tree Item To The Tree Control

Assume for a moment that we have a tree control, and an item we want to add to it. Here are a few specific things we need to know about an item to add it to the tree:

  • What item is the new item’s parent?
  • Does the new item have children?
  • Will the icon next to the new item change if the user selects it from the tree control?

We pass this and other information to the tree control in the TV_INSERTSTRUCT structure, and another structure, TVITEM, which is a member of TV_INSERTSTRUCT. The content of these structures define the rank, behavior, and appearance of the tree item we insert. Here’s the typedef for TV_INSERTSTRUCT.

typedef struct tagTVINSERTSTRUCT {
      HTREEITEM hParent;
      HTREEITEM hInsertAfter;
      TVITEM item;
    } TV_INSERTSTRUCT;

The first member, hParent, is the handle to the parent of the item being inserted. This handle, hParent, was returned when the parent was inserted. Passing a NULL in hParent establishes an item as the root of the hierarchy. The next member, hInsertAfter, is actually a flag, which is assigned one of the following predefined values:

Table 1: Flag Values For The TV_INSERTSTRUCT hInsertAfter Member

Flag Name Meaning
TVI_FIRST Insert item at the head of the list
TVI_LAST Insert item at the end of the list
TVI_SORT Insert sorted alphabetically

The item member (which is a structure of type TVITEM) of the TV_INSERTSTRUCT structure contains the item’s configuration information. TVITEM is used both to set item information when adding to items the tree control and to retrieve information about a particular item. Here’s the typedef of TVITEM:

typedef struct tagTVITEM{
   UINT        mask;            //tells which members are valid or
                                //should be returned
   HTREEITEM   hItem;           //handle to item for which we are
                                //retrieving data, unused if we
                                //are adding the item
   UINT        state;           //Item State Flags
   UINT        stateMask;       //Mask that identifies which bits
                                //of the state mask are valid
   LPTSTR      pszText;         //Item caption
   int         cchTextMax;      //caption buffer size, in
                                //characters
   int         iImage;          //tree control image list index of
                                //the icon to use when the item is
                                //unselected
   int         iSelectedImage;  //tree control image list index of
                                //the icon to use when the item is
                                //selected
   int         cChildren;       //treated as Boolean flag- 1= has
                                //children, 0= no children
   LPARAM      lParam;          //application specific data stored
                                //in the item
} TVITEM, FAR *LPTVITEM;

The key to using the TVITEM structure to set or retrieve information about an item is in understanding the mask, state, and stateMask members.

  • The mask member indicates which members of the TVITEM structure contain valid data if you are adding the item.
  • The mask member indicates which members of the TVITEM structure should contain valid data on return if you are querying the item.
  • Bits 0-7 of the state member contain flags that specify the tree view item’s state.
  • Bits 8-11 of the state member give the one based index of the item’s overlay image.
  • Bits 12-15 of the state member give the application defined state image.
  • The stateMask member defines which bits of the state member are valid.

Notice that the cChildren member is treated as a Boolean flag, even though it is of type int. If the item has children, you should set this value equal to one, not the count of the children, as its name and type seem to imply.

In the CWalkReg::InsertTreeItem() member, initialize the TV_INSERTSTRUCT with a call to memset(). We set the hParent member to the value that was passed as the first parameter to the function. (You’ll see later that we call this function repetitively when we detect that an item has children, passing in the handle to the parent of the item being added.) We set the hInsertAfter to TVI_LAST, which means this item will be added to the bottom of the list. The item.mask member signals that we are passing the handle of the parent item, a caption string, and application defined lParam value, the children flag, and the zero-based indexes in the tree control’s image list for the item’s selected and non-selected state. Notice that we set tvis.item.lParam to the value hThisKey. hThisKey was passed to the InsertTreeItem() member as a parameter, and is the handle to an open Registry key corresponding to the item we are adding to the tree view.

HTREEITEM CWalkReg::InsertTreeItem( HTREEITEM hParent,
                                    TCHAR *pszName, LPARAM lParam,
                                    DWORD nChildren, HKEY hThisKey)
{
   TV_INSERTSTRUCT tvis;

   // Initialize the insertstruct.
   memset (&tvis, 0, sizeof (tvis));
   tvis.hParent      = hParent;
   tvis.hInsertAfter = TVI_LAST;
   tvis.item.mask    = TVIF_HANDLE | TVIF_TEXT | TVIF_PARAM |
                       TVIF_CHILDREN | TVIF_IMAGE |
                       TVIF_SELECTEDIMAGE ;
   tvis.item.pszText        = pszName;
   tvis.item.cchTextMax     = lstrlen (pszName);
   tvis.item.iImage         = 0;
   tvis.item.iSelectedImage = 1;
   tvis.item.lParam         = (LPARAM)hThisKey;
   if (nChildren)
      tvis.item.cChildren   = 1;
   else
      tvis.item.cChildren   = 0;

Once the structures are properly initialized, a call to m_RegTree.InsertItem() adds the item and updates the tree control’s appearance. We return the handle to the newly created tree item to the calling function.

   HTREEITEM htiSuccess = m_RegTree.InsertItem(&tvis );

   return htiSuccess;
}

Looking Ahead

In the next installment, we’ll see how to handle the tree control notification messages. These messages allow us to interact with the user’s command to expand or collapse the tree and to update the tree’s membership when its constituents change.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read