Implement tree control with background bitmap in VC

Source: Internet
Author: User
Currently, many applications have added background bitmaps for tree controls to enhance the charm of controls. However, for Visual C ++ programmers, using the tree control (ctreectrl) provided by Visual C ++ MFC is a difficult issue. It is even more confusing to make the control carry a background bitmap. In this example, the ctreectrl class is enhanced, which not only carries a background bitmap, but also solves the problem of background bitmap flashing when the tree control is clicked. In addition, by using the control in the dialog box to display the three-level directory, the basic usage of the tree control is demonstrated. Run the compiled program:

Figure 1 tree control with background image

   I. Implementation Method

Before implementing the background bitmap of a tree control, we will first introduce the basic usage of the tree control. Tree control is widely used in the system. For example, Windows resource manager is a typical example. The tree control can be used in a tree structure. One root node has many subnodes, and one or more or no subnodes are allowed on each subnode.

In MFC, The ctreectrl class is used to encapsulate various operations of the tree control. By calling bool create (DWORD dwstyle, const rect & rect, cwnd * pparentwnd, uint NID), a window is created, in dwstyle, you can use the following special tree controls: tvs_haslines draw lines between parent and child nodes; tvs_linesatroot draw lines between root and child nodes; tvs_hasbuttons adds a button before each node to indicate whether the current node has been expanded; the display character of the tvs_editlabels node can be edited; tvs_showselalways also displays the selected node when the focus is lost; tvs_disabledragdrop does not allow drag/drop; tvs_notooltips does not use tooltip to display node display characters.

In the tree control, each node has a handle (htreeitem). When adding a knot, the parameter must be the parent node handle of the node (where the root node has only one, htreeitem insertitem (lpctstr lpszitem, htreeitem hparent = tvi_root, htreeitem hinsertafter = tvi_last) can be used to add a node with pszitem as the display character, hparent indicates the handle of the parent node. The currently added node is placed behind the node indicated by hinsertafter. The returned value is the handle of the currently created node.

If you want to add a small icon before each node, you must first call the ctreectrl class member function cimagelist * setimagelist (cimagelist * pimagelist, int nimagelisttype ), specifies the image list (imagelist) used by the current control. The nimagelisttype is tvsil_normal. After the call is complete, use the image in the control based on the image in the Set imagelist. Then call htreeitem insertitem (lpctstr lpszitem, int nimage, int nselectedimage, htreeitem hparent = tvi_root, htreeitem hinsertafter = tvi_last) to add the node, the nimage parameter indicates the image sequence number used when the node is not selected, and the nselectedimage parameter indicates the image sequence number used when the node is selected.

In addition, ctreectrl provides some functions for obtaining/modifying the control status:

· Htreeitem getselecteditem () returns the handle of the currently selected node;

· Bool selectitem (htreeitem hitem) selects the specified node;

· Bool indexes (htreeitem hitem, Int & nimage, Int & nselectedimage)/bool setitemimage (htreeitem hitem, int nimage, int nselectedimage) are used to obtain/modify the icon indexes used by a node;

· Cstring getitemtext (htreeitem hitem)/bool setitemtext (htreeitem hitem, lpctstr lpszitem) is used to obtain/modify the display characters of a node;

· Bool deleteitem (htreeitem hitem) is used to delete a node. bool deleteallitems () deletes all nodes.

In addition, you can use the following functions to traverse the tree:

· Htreeitem getrootitem () to obtain the root node;

· Htreeitem getchilditem (htreeitem hitem) to obtain the subnode;

· Htreeitem getprevsiblingitem/getnextsiblingitem (htreeitem hitem) obtains the upper/next sibling node of the specified node;

· Htreeitem getparentitem (htreeitem hitem) obtains the parent node.

The message ing of the tree control uses the on_notify macro in the form of on_notify (wnotifycode, ID, memberfxn). wnotifycode is the notification code, ID is the window ID that generates the message, and memberfxn is the processing function, the function prototype is like void onxxxtree (nmhdr * pnmhdr, lresult * presult). Among them, pnmhdr is a data structure, which needs to be converted to other types of structures during use. The values of the tree control and the corresponding data structure are as follows:

· TVN _ selchanged is sent after the selected node changes. The structure used is nmtreeview;

· TVN _ itemexpanded is sent after a node is expanded. The structure used is nmtreeview;

· TVN _ beginlabeledit is sent when you start to edit node characters. The structure used is nmtvdispinfo;

· TVN _ endlabeledit is sent when the edit Node Character ends. The structure used is nmtvdispinfo;

· TVN _ getdispinfo is sent when a node information needs to be obtained (for example, the structure used to obtain the display characters of the node): nmtvdispinfo;

The standard tree control ctreectrl provided by Visual C ++ MFC does not support Background bitmaps. To implement background bitmaps, you must first display the default Treeview plot on the in-memory CDC object, then, select the background bitmap and combine it with the default bitmap. In this way, the standard Treeview window is pasted on the basemap. This operation is completed in the memory. At the same time, to avoid flickering, The onitemexpanding () and onitemexpanded () functions must be reloaded. The setredraw function is used to ensure that you do not redraw a child node when it is popped up. Instead, you can re-draw a child node after it has been expanded. To this end, the routine defines cmytreectrl, a subclass of the ctreectrl class, and reloads the following member functions:

Bool cmytreectrl: setbkimage (lpctstr lpszresource)
Void cmytreectrl: onpaint ()
Void cmytreectrl: onitemexpanding (nmhdr * pnmhdr, lresult * presult)
Void cmytreectrl: onitemexpanded (nmhdr * pnmhdr, lresult * presult)
Bool cmytreectrl: onerasebkgnd (CDC * PDC)

   Ii. programming steps

1. Start visual c ++ 6.0, generate a project tree based on the dialog box, and place a tree control component on the Framework. Its ID Identifier is idc_tree1;

2. After creating the cmytreectrl class, use classwizard to add message ing for it:

On_policy_reflect (tvn_itemexpanded, onitemexpanded) on_policy_reflect (tvn_itemexpanding, onitemexpanding)

Message response function:

Afx_msg void onitemexpanded (nmhdr * pnmhdr, lresult * presult );
Afx_msg void onitemexpanding (nmhdr * pnmhdr, lresult * presult );

3. Associate the tree control with the cmytreectrl class. In the dialog box, add the cmytreectrl m_ctrltree variable;

4. Create a bitmap to be used as the background of the tree control;

5. Modify the initialization function bool ctreedlg: oninitdialog ();

6. Add code and compile and run the program.

Iii. Implementation Code

//////////////////////////////////////// /////////
# If! Defined (afx_treedlg_h1_d82db384_f574_44a7_96da_6ec9068e22b11_included _)
# Define afx_treedlg_h1_d82db384_f574_44a7_96da_6ec9068e22b11_included _
# If _ msc_ver> 1000
# Pragma once
# Endif // _ msc_ver> 1000

//////////////////////////////////////// /// Ctreedlg Dialog
# Include "mytreectrl. H"
Class ctreedlg: Public cdialog
{
// Construction
Public:
Ctreedlg (cwnd * pparent = NULL); // standard Constructor

// Dialog data
// {Afx_data (ctreedlg)
Enum {IDD = idd_tree_dialog };
Cmytreectrl m_ctrltree;
//} Afx_data

// Classwizard generated virtual function overrides
// {Afx_virtual (ctreedlg)
Protected:
Virtual void dodataexchange (cdataexchange * PDX); // DDX/DDV support
//} Afx_virtual

// Implementation
Protected:
Hicon m_hicon;

// Generated message map Functions
// {Afx_msg (ctreedlg)
Virtual bool oninitdialog ();
Afx_msg void onsyscommand (uint NID, lparam );
Afx_msg void onpaint ();
Afx_msg hcursor onquerydragicon ();
//} Afx_msg
Declare_message_map ()
};

# Endif

/// // Mytreectrl. cpp: implementation file

# Include "stdafx. H"
# Include "tree. H"
# Include "mytreectrl. H"
# Ifdef _ debug
# Define new debug_new
# UNDEF this_file
Static char this_file [] = _ file __;
# Endif

//// // Cmytreectrl

Cmytreectrl: cmytreectrl ()
{}

Cmytreectrl ::~ Cmytreectrl ()
{}

Begin_message_map (cmytreectrl, ctreectrl)
// {Afx_msg_map (cmytreectrl)
On_wm_paint ()
On_wm_erasebkgnd ()
On_policy_reflect (tvn_itemexpanded, onitemexpanded)
On_policy_reflect (tvn_itemexpanding, onitemexpanding)
//} Afx_msg_map
End_message_map ()

//////////////////////////////////////// /////////////////////////////////////
// Cmytreectrl message handlers
Bool cmytreectrl: setbkimage (lpctstr lpszresource)
{
// If this is not the first call then delete GDI objects
If (m_bitmap.m_hobject! = NULL)
M_bitmap.deleteobject ();

Hbitmap hbmp = (hbitmap): LoadImage (AfxGetInstanceHandle (),
Lpszresource, image_bitmap, 0, 0, lr_createdibsection | lr_loadfromfile );

If (hbmp = NULL)
Return false;
M_bitmap.attach (hbmp );
Return true;
}

Lresult cmytreectrl: windowproc (uint message, wparam, lparam)
{
// Todo: add your specialized code here and/or call the base class
Return ctreectrl: windowproc (message, wparam, lparam );
}

Void cmytreectrl: onpaint ()
{
Cpaintdc DC (this); // device context for painting
Crect rcclient;
Getclientrect (& rcclient );

// Create a compatible memory DC
CDC memdc;
Memdc. createcompatibledc (& DC );
Cbitmap bitmap;
Bitmap. createcompatiblebitmap (& DC, rcclient. Width (), rcclient. Height ());
Memdc. SelectObject (& Bitmap );
Cwnd: defwindowproc (wm_paint, (wparam) memdc. m_hdc, 0 );
CDC maskdc;
Maskdc. createcompatibledc (& DC );
Cbitmap maskbitmap;
Maskbitmap. createbitmap (rcclient. Width (), rcclient. Height (), 1, 1, null );
Maskdc. SelectObject (& maskbitmap );
Maskdc. bitblt (0, 0, rcclient. Width (), rcclient. Height (), & memdc,
Rcclient. Left, rcclient. Top, srccopy );
Cbrush brush;
Brush. createpatternbrush (& m_bitmap );
DC. fillrect (rcclient, & brush );
Memdc. setbkcolor (RGB (0, 0, 0 ));
Memdc. settextcolor (RGB (255,255,255 ));
Memdc. bitblt (rcclient. Left, rcclient. Top, rcclient. Width (), rcclient. Height (), & maskdc, rcclient. Left, rcclient. Top, srcand );
DC. setbkcolor (RGB (255,255,255 ));
DC. settextcolor (RGB (0, 0 ));
DC. bitblt (rcclient. Left, rcclient. Top, rcclient. Width (), rcclient. Height (), & maskdc, rcclient. Left, rcclient. Top, srcand );
DC. bitblt (rcclient. Left, rcclient. Top, rcclient. Width (), rcclient. Height (), & memdc, rcclient. Left, rcclient. Top, srcpaint );
Brush. deleteobject ();
}

Bool cmytreectrl: onerasebkgnd (CDC * PDC)
{
// Todo: add your message handler code here and/or call default
Return true;
}

Void cmytreectrl: onitemexpanded (nmhdr * pnmhdr, lresult * presult)
{
Nm_treeview * pnmtreeview = (nm_treeview *) pnmhdr;
// Todo: add your control notification handler code here
Invalidate ();
Setredraw (true );
* Presult = 0;
}

Void cmytreectrl: onitemexpanding (nmhdr * pnmhdr, lresult * presult)
{
Nm_treeview * pnmtreeview = (nm_treeview *) pnmhdr;
// Todo: add your control notification handler code here
Setredraw (false );

* Presult = 0;
}

//////////////////////////////////////// ///////////////
Bool ctreedlg: oninitdialog ()
{
Cdialog: oninitdialog ();
// Add "about..." menu item to system menu.
// Idm_aboutbox must be in the system command range.
Assert (idm_aboutbox & 0xfff0) = idm_aboutbox );
Assert (idm_aboutbox <0xf000 );
Cmenu * psysmenu = getsystemmenu (false );
If (psysmenu! = NULL)
{
Cstring straboutmenu;
Straboutmenu. loadstring (ids_aboutbox );
If (! Straboutmenu. isempty ())
{
Psysmenu-> appendmenu (mf_separator );
Psysmenu-> appendmenu (mf_string, idm_aboutbox, straboutmenu );
}
}
// Set the icon for this dialog. The framework does this automatically
// When the application's main window is not a dialog
Seticon (m_hicon, true); // set big icon
// Todo: add extra initialization here
M_ctrltree.setbkimage ("idb_bitmap1 ");
Seticon (m_hicon, false); // set small icon
Tvinsertstruct tvinsert;
Tvinsert. hparent = NULL;
Tvinsert. hinsertafter = NULL;
Tvinsert. item. Mask = tvif_text;
Tvinsert. item. psztext = _ T ("Visual C ++ programming instance ");
Htreeitem hcountry = m_ctrltree.insertitem (& tvinsert );
Htreeitem HPA = m_ctrltree.insertitem (tvif_text,
_ T ("document center"), 0, 0, 0, 0, 0, hcountry, null );
Htreeitem Hwa = m_ctrltree.insertitem (_ T ("Code Center"), 0, 0, hcountry, HPA );
M_ctrltree.insertitem (_ T ("full screen Program Implementation"), HPA, tvi_sort );
M_ctrltree.insertitem (_ T ("arbitrary window segmentation"), HPA, tvi_sort );
M_ctrltree.insertitem (_ T ("implement menu self-painting"), HPA, tvi_sort );
M_ctrltree.insertitem (_ T ("Code for full screen display"), Hwa, tvi_sort );
M_ctrltree.insertitem (_ T ("code with arbitrary window Division"), Hwa, tvi_sort );
M_ctrltree.insertitem (_ T ("menu self-painted Code"), Hwa, tvi_sort );
M_ctrltree.expand (hcountry, tve_expand );
Return true; // return true unless you set the focus to a control
}

   Iv. Summary

So far, this example introduces some Tree View control programming methods by implementing the background bitmap of the tree control, including the establishment of the Tree View control and the granting of node values. Of course, it is widely used and used in many ways. This only involves the basic framework for building Tree View Controls. Readers can expand on this basis to achieve more powerful functions. Interested readers may wish to extend the control by themselves.

Source: Tianji Development

Address: http://www.7880.com/Info/Article-7cf793c0.html

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.