Custom Draw Tree Control

MFC 6 supports Custom Draw Tree Control, which makes setting different colors for individual tree items much simpler (see Zafir Anjum's article "Setting color and font attribute for individual items" to find out how to do it without Custom Draw support). Custom draw tree control sends an NM_CUSTOMDRAW notification to its owner. The trick is that the control sends first NM_CUSTOMDRAW notification with dwDrawStage set to CDDS_PREPAINT, and no further notifications will be sent, unless this notification is processed correctly. Setting pResult to CDRF_NOTIFYITEMDRAW causes the control to send NM_CUSTOMDRAW notifications for individual items with dwDrawStage set to CDDS_ITEMPREPAINT, which allows changing item's attributes before it is drawn.



BOOL CMainFrame::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) 
{
	LPNMHDR pNmhdr = (LPNMHDR)lParam;

	switch (pNmhdr->code)
	{
		case NM_CUSTOMDRAW:
		{
			LPNMTVCUSTOMDRAW pCustomDraw = (LPNMTVCUSTOMDRAW)lParam;
			switch (pCustomDraw->nmcd.dwDrawStage)
			{
				case CDDS_PREPAINT:
					// Need to process this case and set pResult to CDRF_NOTIFYITEMDRAW, 
					// otherwise parent will never receive CDDS_ITEMPREPAINT notification. (GGH) 
					*pResult = CDRF_NOTIFYITEMDRAW;
					return true;

				case CDDS_ITEMPREPAINT:
					switch (pCustomDraw->iLevel)
					{
						// painting all 0-level items blue,
						// and all 1-level items red (GGH)
						case 0:
							if (pCustomDraw->nmcd.uItemState == (CDIS_FOCUS | CDIS_SELECTED)) // selected
								pCustomDraw->clrText = RGB(255, 255, 255);
							else	
								pCustomDraw->clrText = RGB(0, 0, 255);
							break;
						case 1:
							if (pCustomDraw->nmcd.uItemState == (CDIS_FOCUS | CDIS_SELECTED)) // selected
								pCustomDraw->clrText = RGB(255, 255, 255);
							else	
								pCustomDraw->clrText = RGB(255, 0, 0);
							break;
					}
					
					*pResult = CDRF_SKIPDEFAULT;
					return false;

			}
		}
		break;
	}
	
		
	return CFrameWnd::OnNotify(wParam, lParam, pResult);
}


Download demo project - 22 KB

Download source - 1.4 KB



Comments

  • how can i add list view for the same

    Posted by vishal_pansari on 08/20/2004 01:12am

    This is really a very good code. but tell me, how can i add list view for the same to the right side of the window. ??

    • vishal sir plz contact me, paras from indore

      Posted by thematrix4u on 12/17/2008 01:51am

      hello vishal sir,
      i donot know that this mail will reach to u or not,
      but sir kindly contact me this is an emergancy,,,
      i m paras patidar from indore..
      Dr. Rama's family friend..
      i tried ur no. but it is not in service..
      
      contact me at +91-9009784488
      plz sir i need to talk somthing important to u for both of us.
      
      
      regards:
      
      paras patidar

      Reply
    Reply
  • Can i apply the same logic to a scrollbar?

    Posted by Legacy on 01/27/2004 12:00am

    Originally posted by: prashanth prabhu p

    I would like to know wether the windows scrollbar control supports customdraw and wether the same logic could be applied for drawing a custom scrollbar.

    Reply
  • changing item RECT workaround

    Posted by Legacy on 10/28/2002 12:00am

    Originally posted by: David Woods

    I've seen several posts here about changing the item rect when doing a custom draw, and in fact it was searching for that information that led me to this page in the first place.  I've had luck with one ... not a solution, more like a work-around.
    
    

    It's pretty simple to implement -- just increase the TreeCtrl Indent by the size of your icon, then in the custom draw function, offset your item rectangle by the same amount in the other direction:

    // when initializing CTreeCtrl, assuming icon width of 16
    MyTree.SetIndent(MyTree.GetIndent() + 16);

    // inside CustomDraw function
    HTREEITEM hti = (HTREEITEM)nmcd.dwItemSpec;
    CRect itemRect;
    GetItemRect(hti, &itemRect, TRUE);
    // only reverse the indent offset if this is a child item
    if (GetParentItem(hti) != TVI_ROOT && GetParentItem(hti) != NULL)
    ::OffsetRect(&itemRect, -16, 0);


    cheers!
    -david

    Reply
  • how to make a transparent CTreeCtrl

    Posted by Legacy on 10/06/2002 12:00am

    Originally posted by: Nitin Dbey

    i am trying to make transparent tree control, i have tryed to make it by selecting the options given in the properties window of CTreeCtrl. but its not working

    thankz

    Reply
  • treeview customdraw and why horizontal scrolling does not work

    Posted by Legacy on 11/28/2001 12:00am

    Originally posted by: lammerville

    I draw my personnal image and text like this
    but horizontal scrolling does not work, why ?

    void CViewArbre::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
    {
    NMTVCUSTOMDRAW* pTVCD = (NMTVCUSTOMDRAW*)pNMHDR;
    // TODO: Add your control notification handler code here

    *pResult = 0;

    switch (pTVCD->nmcd.dwDrawStage)
    {
    case CDDS_PREPAINT:
    *pResult = CDRF_NOTIFYITEMDRAW ;
    break;
    case CDDS_ITEMPREPAINT:
    {
    CDC* pDC = CDC::FromHandle(pTVCD->nmcd.hdc);
    CRect rc(pTVCD->nmcd.rc);
    CRect rcImg(pTVCD->nmcd.rc);
    POINT p;
    rcImg.OffsetRect(pTVCD->iLevel*16,0) ;
    p=rcImg.TopLeft();
    rc.OffsetRect(rcImg.left+16,0);
    p=rcImg.TopLeft();
    m_il.Draw(pDC,0,p,ILD_NORMAL);
    CString strTexte = GetTreeCtrl().GetItemText((HTREEITEM)pTVCD->nmcd.dwItemSpec);
    pDC->TextOut(rc.left,rc.top,strTexte) ;
    TRACE("%d %d,%d sur %d x %d\n",rand(),rc.left,rc.top,rc.Width(),rc.Height());
    }
    *pResult = CDRF_SKIPDEFAULT ;
    break;
    }

    }

    Reply
  • ExTree

    Posted by Legacy on 10/18/2001 12:00am

    Originally posted by: Mike Philis

    Are you looking for a cool tree control?
    
    

    Check this out: http://www.exontrol.com/sg.jsp?content=products/extree

    Features include:
    ActiveX hosting, events from contained components are fired through to your program using the exact same model used in VB6 for components added at run time, data bounding, multiple columns, and more

    Mike
    www.exontrol.com

    Reply
  • how to get a CDDS_ITEMPOSTPAINT?

    Posted by Legacy on 10/20/2000 12:00am

    Originally posted by: Don Metzler

    How can I ensure that I will get a CDDS_ITEMPOSTPAINT notification?

    Thanks,

    Don

    Reply
  • Solution : I don't get a CDDS_ITEMPREPAINT message

    Posted by Legacy on 01/07/2000 12:00am

    Originally posted by: Nikolai Sander

    In case you don't get a CDDS_ITEMPREPAINT message after returning CDRF_NOTIFYITEMDRAW to the CDDS_PREPAINT, you can try to set SetWindowLong(hDlg,DWL_MSGRESULT,CDRF_NOTIFYITEMDRAW); in case you have a dialog box.

    Nikolai

    Reply
  • How to change item-size ?

    Posted by Legacy on 10/27/1999 12:00am

    Originally posted by: Martin Thoma

    Hi !

    The Custom-Draw-TreeCtrl works fine. But now I want to set the width of each item, so I can draw something instead of text. The main problem is, that the scroll-bar will only notice the width of the text, but I want to set a user-defined width. Is this possible ?

    Regards

    Martin

    Reply
  • Changing the color of a selected item in a MFC CTreeView

    Posted by Legacy on 07/15/1999 12:00am

    Originally posted by: Carl Bomgardner

    I made the following changes to the code so that I could
    
    change the color of the selected item to the Tree Control
    embedded in the MFC's CTreeView.

    The CTreeView routine is notified when the tree item is to
    be painted (via the NM_CUSTOMDRAW notification) through the
    OnChildNotify rather than the OnNotify member function.


    BOOL CLeftView::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
    {
    LPNMHDR pNmhdr = (LPNMHDR)lParam;
    int select=0;
    if (message==WM_NOTIFY) {
    if (pNmhdr->code == NM_CUSTOMDRAW) {
    LPNMTVCUSTOMDRAW pCustomDraw = (LPNMTVCUSTOMDRAW)lParam;
    switch (pCustomDraw->nmcd.dwDrawStage)
    {
    case CDDS_PREPAINT:
    // Need to process this case and set pResult to CDRF_NOTIFYITEMDRAW,
    // otherwise parent will never receive CDDS_ITEMPREPAINT notification. (GGH)
    *pResult = CDRF_NOTIFYITEMDRAW;
    return true;

    case CDDS_ITEMPREPAINT:
    CTreeCtrl& refCtrl = GetTreeCtrl();
    if (pCustomDraw->nmcd.dwItemSpec == (ULONG) refCtrl.GetSelectedItem()) select=1;
    if (select) pCustomDraw->clrText = RGB(0,0,255);
    else pCustomDraw->clrText = RGB(0,0,0);
    pCustomDraw->clrTextBk = RGB(255,255,255);
    *pResult = CDRF_NEWFONT;
    return false;

    }
    }
    }

    return CTreeView::OnChildNotify(message, wParam, lParam, pResult);
    }

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

  • Webinar on September 23, 2014, 2 p.m. ET / 11 a.m. PT Mobile commerce presents an array of opportunities for any business -- from connecting with your customers through mobile apps to enriching operations with mobile enterprise solutions. Join guest speaker, Michael Facemire, Forrester Research, Inc. Principal Analyst, as he discusses the new demands of mobile engagement and how application program interfaces (APIs) play a crucial role. Check out this upcoming webinar to learn about the new set of …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds