CTreeCtrl---树控件自绘

来源:互联网 发布:mac迅雷自带播放器 编辑:程序博客网 时间:2024/06/05 11:22

效果:


1、原理:在CTreeCtrl的派生类CMyTreeCtrl的OnPaint()函数中逐行进行绘制。

2、要点:

                 1)创建CTreeCtrl的派生类CMyTreeCtrl;

                 2)为树型控件绑定一个控件类型变量CMyTreeCtrl  m_Tree;

                 3)设置属性has buttons、Lines at Root、border、horizontal scroll 都为TRUE;

                 4)导入一些必要的图标。

3、实现:

1)在主对话框的OnInitDialog()函数中:

BOOL CCTreeCtrl自绘Dlg::OnInitDialog(){CDialogEx::OnInitDialog();// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动//  执行此操作SetIcon(m_hIcon, TRUE);// 设置大图标SetIcon(m_hIcon, FALSE);// 设置小图标m_IconList.Create(16,16,ILC_COLOR32|ILC_MASK,4,4);m_IconList.Add(AfxGetApp()->LoadIcon(IDI_DOG));m_IconList.Add(AfxGetApp()->LoadIcon(IDI_QIE));m_IconList.Add(AfxGetApp()->LoadIcon(IDI_ADD));m_IconList.Add(AfxGetApp()->LoadIcon(IDI_SUB));m_Tree.GetIconList(&m_IconList);//插入一些测试项HTREEITEM hRoot = m_Tree.InsertItemEx("第1项",0);m_Tree.InsertItemEx("第1.1项",1,hRoot);m_Tree.InsertItemEx("第1.2项",1,hRoot);HTREEITEM hItem = m_Tree.InsertItemEx("第1.3项",0,hRoot);m_Tree.InsertItemEx("第1.3.1项",1,hItem);m_Tree.InsertItemEx("第1.3.2项",1,hItem);hRoot = m_Tree.InsertItemEx("第2项",0);m_Tree.InsertItemEx("第2.1项",1,hRoot);m_Tree.InsertItemEx("第2.2项",1,hRoot);m_Tree.InsertItemEx("第2.3项",1,hRoot);m_Tree.InsertItemEx("第2.4项",1,hRoot);m_Tree.InsertItemEx("第2.5项",1,hRoot);m_Tree.InsertItemEx("第2.6项",1,hRoot);return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE}

2)派生类中的实现(已有详细注释)

.h文件:

#pragma once#include "map"using namespace  std;// CMyTreeCtrlstruct ITEM_DATA //存放每一项的文本和Icon索引{CString strText;int nIconIndex;ITEM_DATA(){strText.Empty();nIconIndex = 0;}};class CMyTreeCtrl : public CTreeCtrl{DECLARE_DYNAMIC(CMyTreeCtrl)public:CFont m_RootFont;                                //根节点的字体  CFont m_ChildFont;                               //子结点的字体CPoint m_mouseOldPoint;                          //上一次鼠标所在的位置HTREEITEM m_CurMouseItem;                        //当前鼠标移动到的节点句柄map<HTREEITEM,ITEM_DATA*> m_mapItemData;          //某一项的句柄<--->某一项对应的文本和Iconmap<HTREEITEM,ITEM_DATA*>::iterator m_iter;       //对应类型的迭代器CRect m_ClientRect;                              //树控件客户端大小CImageList* m_pBmpList;                          //存放bitmapCImageList* m_pIconList;                         //存放ICONCImageList* GetBmpList(CImageList* pBmpList);    //没用到CImageList* GetIconList(CImageList* pIconList);  //得到Iconafx_msg void OnPaint();afx_msg void OnMouseMove(UINT nFlags, CPoint point);void DrawBackGround(CDC* pDC);                   //绘制背景void DrawItem(CDC* pDC);                         //绘制树控件中的每一项HTREEITEM InsertItemEx(CString strText,int nIconIndex,            //插入一项数据          HTREEITEM lparent= TVI_ROOT,HTREEITEM lpFont = TVI_LAST);  void DrawItemText(CDC * pDC,HTREEITEM pItem,CRect Rect);//绘制每一项的文本public:CMyTreeCtrl();virtual ~CMyTreeCtrl();protected:DECLARE_MESSAGE_MAP()public:afx_msg void OnLButtonDown(UINT nFlags, CPoint point);};

.cpp:

// MyTreeCtrl.cpp : 实现文件//#include "stdafx.h"#include "CTreeCtrl自绘.h"#include "MyTreeCtrl.h"// CMyTreeCtrlIMPLEMENT_DYNAMIC(CMyTreeCtrl, CTreeCtrl)CMyTreeCtrl::CMyTreeCtrl(){m_pBmpList = NULL;m_pIconList = NULL;m_RootFont.CreateFont(13,                        // nHeight0,                         // nWidth0,                         // nEscapement0,                         // nOrientationFW_BOLD,                   // nWeightFALSE,                     // bItalicFALSE,                     // bUnderline0,                         // cStrikeOutANSI_CHARSET,   // nCharSetOUT_DEFAULT_PRECIS,        // nOutPrecisionCLIP_DEFAULT_PRECIS,       // nClipPrecisionPROOF_QUALITY,             // nQualityDEFAULT_PITCH | FF_SWISS,  // nPitchAndFamily_T("宋体") );              // lpszFacenamem_ChildFont.CreateFont(12,                        // nHeight0,                         // nWidth0,                         // nEscapement0,                         // nOrientationFW_NORMAL,                   // nWeightFALSE,                     // bItalicFALSE,                     // bUnderline0,                         // cStrikeOutANSI_CHARSET,   // nCharSetOUT_DEFAULT_PRECIS,        // nOutPrecisionCLIP_DEFAULT_PRECIS,       // nClipPrecisionPROOF_QUALITY,             // nQualityDEFAULT_PITCH | FF_SWISS,  // nPitchAndFamily_T("宋体") );              // lpszFacename}CMyTreeCtrl::~CMyTreeCtrl()//释放申请的内存{m_iter = m_mapItemData.begin();while (m_iter != m_mapItemData.end()){if (m_iter->second != NULL){delete m_iter->second;m_iter->second = NULL;}++m_iter;}}BEGIN_MESSAGE_MAP(CMyTreeCtrl, CTreeCtrl)ON_WM_PAINT()ON_WM_MOUSEMOVE()ON_WM_LBUTTONDOWN()END_MESSAGE_MAP()// CMyTreeCtrl 消息处理程序CImageList* CMyTreeCtrl::GetBmpList(CImageList* pBmpList){CImageList* pOldBmpList = m_pBmpList;m_pBmpList = pBmpList;return pOldBmpList;}CImageList* CMyTreeCtrl::GetIconList(CImageList* pIconList){CImageList* pOldIconList = m_pIconList;m_pIconList = pIconList;return pOldIconList;}void CMyTreeCtrl::OnPaint(){CPaintDC dc(this); // device context for paintingGetClientRect(&m_ClientRect);//创建兼容的内存DC和位图,并将位图选入到内存DCCBitmap bitmap;CDC MemeDc;MemeDc.CreateCompatibleDC(&dc);bitmap.CreateCompatibleBitmap(&dc,m_ClientRect.Width(),m_ClientRect.Height());CBitmap* pOldBmp = MemeDc.SelectObject(&bitmap);DrawBackGround(&MemeDc);//向兼容的内存DC中绘制背景DrawItem(&MemeDc); //将每一项逐个绘制到树控件上dc.BitBlt( m_ClientRect.left, m_ClientRect.top, m_ClientRect.Width(), m_ClientRect.Height(), &MemeDc, 0, 0,SRCCOPY);MemeDc.SelectObject(pOldBmp);MemeDc.DeleteDC();}void CMyTreeCtrl::DrawBackGround(CDC* pDC){pDC->FillSolidRect(m_ClientRect,RGB(143,175,156));}void CMyTreeCtrl::DrawItem(CDC* pDC){HTREEITEM hCurrentItem,hParentItem;//绘制的当前项句柄和其父句柄DWORD dTreeStyle;//树控件的类型CRect CurItemRect;//当前项的区域int CurItemState;//当前项的状态dTreeStyle =:: GetWindowLong( m_hWnd, GWL_STYLE );//获取树的类型stylehCurrentItem = GetFirstVisibleItem();//获取第一个可见的项,返回它的句柄值do {   //Nonzero if the item is visible, with the bounding rectangle contained in lpRect.//Otherwise, 0 with lpRect uninitialized.if (GetItemRect(hCurrentItem,CurItemRect,1)){CurItemRect.left = CurItemRect.left-20;CRect fillRect(0,CurItemRect.top,m_ClientRect.right,CurItemRect.bottom);//Returns the state of the item specified by hItem.CurItemState = GetItemState(hCurrentItem,TVIF_STATE);//当前正绘制的项已超出窗口的边界,所以不绘制,并退出绘制if (CurItemRect.top > m_ClientRect.bottom)  {break;}//当前节点没有孩子节点,才为其绘制鼠标热点if (hCurrentItem == m_CurMouseItem && ItemHasChildren(hCurrentItem) == NULL){pDC->FillSolidRect(&fillRect,GetSysColor(COLOR_HIGHLIGHTTEXT));}if(CurItemState & TVIS_SELECTED)//当前项的状态有被选中这个状态{pDC->FillSolidRect(&fillRect,GetSysColor(COLOR_HIGHLIGHT));fillRect.DeflateRect(-1,-1);pDC->DrawFocusRect(&fillRect);}//绘制展开图标if (ItemHasChildren(hCurrentItem)){CPoint point;point.x = CurItemRect.left;//x值最左point.y = CurItemRect.top+(CurItemRect.Height()-16)/2;//y值居中if (CurItemState & TVIS_EXPANDED)//当前项展开m_pIconList->Draw(pDC,3,point,ILD_TRANSPARENT);else//当前项没展开m_pIconList->Draw(pDC,2,point,ILD_TRANSPARENT);}//绘制文字前面的图标CurItemRect.left += 16+2;//返回值是map的迭代器m_iter = m_mapItemData.find(hCurrentItem);int nIconIndex = m_iter->second->nIconIndex;m_pIconList->Draw(pDC,nIconIndex,CurItemRect.TopLeft(),ILD_NORMAL);//绘制文字CurItemRect.left += 16+2;CurItemRect.right = m_ClientRect.right;DrawItemText(pDC,hCurrentItem,CurItemRect);}} while ((hCurrentItem = GetNextVisibleItem(hCurrentItem)) != NULL);}HTREEITEM CMyTreeCtrl::InsertItemEx(CString strText,int nIconIndex,HTREEITEM lparent,HTREEITEM lpFont){HTREEITEM hTempTreeItem;hTempTreeItem = InsertItem(strText,lparent,lpFont);ITEM_DATA* pItemData = new ITEM_DATA;pItemData->strText = strText;pItemData->nIconIndex = nIconIndex;//m_mapItemData.insert(make_pair(hTempTreeItem,pItemData));m_mapItemData.insert(pair<HTREEITEM,ITEM_DATA*>(hTempTreeItem,pItemData));return hTempTreeItem;}void CMyTreeCtrl::OnMouseMove(UINT nFlags, CPoint point){m_mouseOldPoint = point;HTREEITEM hItem = HitTest(point);//判断鼠标在控件的哪一项上面if (hItem != NULL && m_CurMouseItem != hItem){m_CurMouseItem = hItem;Invalidate(FALSE);}CTreeCtrl::OnMouseMove(nFlags, point);}void CMyTreeCtrl::DrawItemText(CDC * pDC,HTREEITEM pItem,CRect Rect){if (GetParentItem(pItem) == NULL)//如果是最顶级节点{pDC->SelectObject(&m_RootFont);pDC->SetTextColor(0x000000);}else{if (ItemHasChildren(pItem))//有孩子节点{pDC->SelectObject(&m_RootFont);}else//没孩子节点{pDC->SelectObject(&m_ChildFont);}pDC->SetTextColor(0x000066);}CString ItemText = GetItemText(pItem);CSize  fontSize;fontSize= pDC->GetTextExtent(ItemText);//返回字体的尺寸//让文字显示在矩形垂直的中间位置int middPos;middPos=(Rect.Height()-fontSize.cy)/2;Rect.top += middPos;pDC->SetBkMode(TRANSPARENT);pDC->DrawText(ItemText,Rect,DT_LEFT|DT_TOP);//显示项文本}void CMyTreeCtrl::OnLButtonDown(UINT nFlags, CPoint point){/*HTREEITEM hItem = HitTest(point);int nItemState = GetItemState(hItem,TVIF_STATE);if (hItem != NULL && ItemHasChildren(hItem) != 0){if (nItemState & TVIS_EXPANDED){SetItemState(hItem,GetItemState(hItem,TVIF_STATE) & ~TVIS_EXPANDED,TVIF_STATE);} else{SetItemState(hItem,GetItemState(hItem,TVIF_STATE) || TVIS_EXPANDED,TVIF_STATE);}}*///Invalidate(FALSE);CTreeCtrl::OnLButtonDown(nFlags, point);}