好的代码收藏2

// TreeCtrlBT.cpp : implementation file
//


#include "stdafx.h"
#include "TreeCtrlBT.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/
// CTreeCtrlBT


CTreeCtrlBT::CTreeCtrlBT()
{
m_bEnableRowLine  = true;
m_bEnableRootBk   = true;
m_nImageHeight    = 0;
m_nImageWidth     = 0;
m_nCellWidth  = 4;
m_clrTextNormal   = RGB(0,0,0);
m_clrTextSelect  = RGB( 0xff, 0xff, 0xff );
m_clrRoot_from    = RGB( 0x80, 0xa0, 0xff );
m_clrRoot_to      = RGB( 0x80, 0xa0, 0xff );


m_hItemSelect     = NULL;
m_hItemMouseMove  = NULL;
m_pCurDrawItemMsg = NULL;


m_ptOldMouse.x  = -1;
m_ptOldMouse.y    = -1;


m_FontRoots.CreateFont(
12,                        // nHeight
0,                         // nWidth
0,                         // nEscapement
0,                         // nOrientation
FW_BOLD,                   // nWeight
FALSE,                     // bItalic
FALSE,                     // bUnderline
0,                         // cStrikeOut
ANSI_CHARSET,   // nCharSet
OUT_DEFAULT_PRECIS,        // nOutPrecision
CLIP_DEFAULT_PRECIS,       // nClipPrecision
PROOF_QUALITY,             // nQuality
DEFAULT_PITCH | FF_SWISS,  // nPitchAndFamily
_T("宋体") );              // lpszFacename


m_FontChild.CreateFont(
12,                        // nHeight
0,                         // nWidth
0,                         // nEscapement
0,                         // nOrientation
FW_NORMAL,                   // nWeight
FALSE,                     // bItalic
FALSE,                     // bUnderline
0,                         // cStrikeOut
ANSI_CHARSET,   // nCharSet
OUT_DEFAULT_PRECIS,        // nOutPrecision
CLIP_DEFAULT_PRECIS,       // nClipPrecision
PROOF_QUALITY,             // nQuality
DEFAULT_PITCH | FF_SWISS,  // nPitchAndFamily
_T("宋体") );              // lpszFacename
}


CTreeCtrlBT::~CTreeCtrlBT()
{
RELEASE_GDI_RESOURCE(m_bmpBackgroud);
RELEASE_GDI_RESOURCE(m_FontRoots);
RELEASE_GDI_RESOURCE(m_FontChild);


if ( m_ImageList.GetSafeHandle() ) m_ImageList.DeleteImageList();


ITEMMSG_MAP::iterator item = m_itmemsg_map.begin();
for ( ; item != m_itmemsg_map.end(); item++)
{
delete item->second;
}
}


BEGIN_MESSAGE_MAP(CTreeCtrlBT, CTreeCtrl)
//{{AFX_MSG_MAP(CTreeCtrlBT)
ON_WM_PAINT()
ON_WM_SIZE()
ON_WM_MOUSEMOVE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/
// CTreeCtrlBT message handlers


void CTreeCtrlBT::PreSubclassWindow() 
{
SetItemHeight(25);
m_nItemHeight = 25; //保存单元项目高度


CTreeCtrl::PreSubclassWindow();
}


void CTreeCtrlBT::OnSize(UINT nType, int cx, int cy) 
{
CTreeCtrl::OnSize(nType, cx, cy);

// TODO: Add your message handler code here

Calculate();
}


void CTreeCtrlBT::OnPaint() 
{
CPaintDC dc(this); // device context for painting

//Calculate();


CBitmap bitmap;
CDC MemeDc;
MemeDc.CreateCompatibleDC(&dc);
bitmap.CreateCompatibleBitmap(&dc, m_rect.Width(), m_rect.Height());
CBitmap *pOldBitmap = MemeDc.SelectObject(&bitmap);

DrawBackgroudBitmap(&MemeDc);
DrawItem(&MemeDc);


dc.BitBlt( m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(), &MemeDc, 0, 0, SRCCOPY);

MemeDc.SelectObject(pOldBitmap);
MemeDc.DeleteDC();
}


void CTreeCtrlBT::Calculate()
{
GetClientRect(&m_rect);
SCROLLINFO scroll_info;
// Determine window portal to draw into taking into account
// scrolling position
if ( GetScrollInfo( SB_HORZ, &scroll_info, SIF_POS | SIF_RANGE ) )
{
m_h_offset = -scroll_info.nPos;
m_h_size = max( scroll_info.nMax+1, m_rect.Width());
}
else
{
m_h_offset = m_rect.left;
m_h_size = m_rect.Width();
}
if ( GetScrollInfo( SB_VERT, &scroll_info, SIF_POS | SIF_RANGE ) )
{
if ( scroll_info.nMin == 0 && scroll_info.nMax == 100) 
scroll_info.nMax = 0;
m_v_offset = -scroll_info.nPos * GetItemHeight();
m_v_size = max( (scroll_info.nMax+2)*((int)GetItemHeight()+1), m_rect.Height() );
}
else
{
m_v_offset = m_rect.top;
m_v_size = m_rect.Height();
}
}


ITEM_MSG* CTreeCtrlBT::GetItemMsg(HTREEITEM hItem)
{
if ( !hItem )
{
return NULL;
}


ITEM_MSG* pItemMsg = NULL;


ITEMMSG_MAP::iterator item = m_itmemsg_map.find(hItem);
if ( item != m_itmemsg_map.end() )
{
pItemMsg = item->second;
}


return pItemMsg;
}


void CTreeCtrlBT::GradientFillRect( CDC *pDC, CRect &rect, COLORREF col_from, COLORREF col_to, bool vert_grad )
{
TRIVERTEX        vert[2];
GRADIENT_RECT    mesh;

vert[0].x      = rect.left;
vert[0].y      = rect.top;
vert[0].Alpha  = 0x0000;
vert[0].Blue   = GetBValue(col_from) << 8;
vert[0].Green  = GetGValue(col_from) << 8;
vert[0].Red    = GetRValue(col_from) << 8;

vert[1].x      = rect.right;
vert[1].y      = rect.bottom; 
vert[1].Alpha  = 0x0000;
vert[1].Blue   = GetBValue(col_to) << 8;
vert[1].Green  = GetGValue(col_to) << 8;
vert[1].Red    = GetRValue(col_to) << 8;

mesh.UpperLeft  = 0;
mesh.LowerRight = 1;
#if _MSC_VER >= 1300  // only VS7 and above has GradientFill as a pDC member
pDC->GradientFill( vert, 2, &mesh, 1, vert_grad ? GRADIENT_FILL_RECT_V : 
GRADIENT_FILL_RECT_H );
#else
GradientFill( pDC->m_hDC, vert, 2, &mesh, 1, vert_grad ? GRADIENT_FILL_RECT_V : 
GRADIENT_FILL_RECT_H );
#endif
}


void CTreeCtrlBT::DrawBackgroudBitmap(CDC* pDc)
{
if ( m_bmpBackgroud.GetSafeHandle() )
{
BITMAP bitmap;
m_bmpBackgroud.GetBitmap(&bitmap);
CDC dctmp;

dctmp.CreateCompatibleDC(NULL);
CBitmap* pOldBitmap = dctmp.SelectObject( &m_bmpBackgroud ); 

pDc->StretchBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(), &dctmp, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY );


dctmp.SelectObject(pOldBitmap);
}
else
{
pDc->FillSolidRect( m_rect, pDc->GetBkColor() ); 
}
}


void CTreeCtrlBT::DrawItem( CDC *pDC )
{
// draw items
HTREEITEM show_item,parent; //当前项句柄,以及它的父窗口句柄
CRect rc_item; //项的区域
DWORD tree_style; //树的类型
int state; //某一项的状态
bool selected; //True:表示是需要高亮
bool has_children; //True:表示是不可以展开或者收缩

show_item = GetFirstVisibleItem();//获取第一个可见项的句柄
if ( show_item == NULL )
return;

tree_style = ::GetWindowLong( m_hWnd, GWL_STYLE ); //获取TREE的类型

do
{
state = GetItemState( show_item, TVIF_STATE );//获取某一项的状态
parent = GetParentItem( show_item );  //获取某一项的父窗口句柄

has_children = ItemHasChildren( show_item ) || parent == NULL;

selected = (state & TVIS_SELECTED) && ((this == GetFocus()) || 
(tree_style & TVS_SHOWSELALWAYS));

if ( GetItemRect( show_item, rc_item, TRUE ) )//获取某一项的矩形区域
{
CRect rcclient;
GetClientRect(rcclient);
if (rc_item.top >= rcclient.bottom)
{
break; //不可见的时候,就不需要再绘制
}

m_pCurDrawItemMsg = GetItemMsg(show_item);


CRect rect;
rect.top = rc_item.top;
rect.bottom = rc_item.bottom-1;
rect.right = m_h_size + m_h_offset;
rect.left = m_h_offset;


//绘制横线
DrawRowLine(CPoint(rect.left,rect.bottom), CPoint(rect.right,rect.bottom), pDC);

if ( has_children  )
{
//绘制根节点背景
if ( m_bEnableRootBk )
{
//GradientFillRect( pDC, rect, m_clrRoot_from, RGB(196,220,247), FALSE );
}
else if ( m_hItemMouseMove == show_item ) //热跟踪
{
//GradientFillRect( pDC, rect, RGB(238,238,238), RGB(238,238,238), FALSE );
}


//绘制展开收缩
DrawExpand(rc_item,state,pDC);

//绘制项位图
DrawItemBitmap(rc_item,show_item,pDC);
}
else
{
if ( selected ) //选中时候的子项背景
{
GradientFillRect( pDC, rect, RGB(11,111,222), RGB(11,111,222), FALSE );
}
else if ( m_hItemMouseMove == show_item ) //热跟踪
{
GradientFillRect( pDC, rect, RGB(238,238,238), RGB(238,238,238), FALSE );
}

//绘制项位图
DrawItemBitmap(rc_item,show_item,pDC);
}

//绘制文本
DrawItemText(rc_item,show_item,selected,pDC);
}

} while ( (show_item = GetNextVisibleItem( show_item )) != NULL );
}


void CTreeCtrlBT::DrawRowLine(CPoint ptBegin,CPoint ptEnd,CDC *pDc /* = NULL */)
{
if ( !IsEnableRowLine() )
{
return;
}

if ( NULL == pDc)
{
CClientDC dc(this);
pDc = &dc;
}

CPen pen(PS_SOLID, 1, RGB(235,235,235) );//RGB(235,235,235)
CPen *pOldPen = pDc->SelectObject(&pen);
pDc->MoveTo(ptBegin);
pDc->LineTo(ptEnd);
pDc->SelectObject(pOldPen);
pen.DeleteObject();
}


void CTreeCtrlBT::DrawExpand(CRect rect, int state, CDC *pDc /* = NULL */)
{
if ( !m_ImageList.GetImageCount())
{
return;
}

if ( NULL == pDc)
{
CClientDC dc(this);
pDc = &dc;
}

int nImage = 0;
if ( state & TVIS_EXPANDED ) //展开
{
nImage = 1;
}
else //收缩
{
nImage = 0;
}

CPoint point;
point.x = rect.left - m_nImageWidth-m_nCellWidth;
point.y = rect.top+(rect.Height()-m_nImageHeight)/2;

m_ImageList.Draw(pDc,nImage, point, ILD_TRANSPARENT);
}


void CTreeCtrlBT::DrawItemBitmap(CRect rect, HTREEITEM hItem, CDC *pDc /* = NULL */)
{
if ( NULL == pDc)
{
CClientDC dc(this);
pDc = &dc;
}


if ( m_pCurDrawItemMsg && m_pCurDrawItemMsg->ItemBitmap.GetSafeHandle() )
{
BITMAP bitmap;
m_pCurDrawItemMsg->ItemBitmap.GetBitmap(&bitmap);

CDC tmpdc;
tmpdc.CreateCompatibleDC(pDc);
CBitmap *pOldBitmap = tmpdc.SelectObject(&m_pCurDrawItemMsg->ItemBitmap);

int nXOriginDest = rect.left; // 目标X偏移
int nYOriginDest = rect.top+(rect.Height()-bitmap.bmHeight)/2; // 目标Y偏移
int nWidthDest = bitmap.bmWidth; // 目标宽度
int hHeightDest  = bitmap.bmHeight; // 目标高度
::TransparentBlt(pDc->m_hDC,nXOriginDest,nYOriginDest,nWidthDest,hHeightDest,
tmpdc.m_hDC,0,0,bitmap.bmWidth,bitmap.bmHeight,RGB(255,255,255));
tmpdc.SelectObject(pOldBitmap);

tmpdc.DeleteDC();
}
}


void CTreeCtrlBT::DrawItemText(CRect rect, HTREEITEM hItem, bool bselected,CDC *pDc /* = NULL */)
{
if ( NULL == pDc)
{
CClientDC dc(this);
pDc = &dc;
}

if ( m_pCurDrawItemMsg&& m_pCurDrawItemMsg->ItemBitmap.GetSafeHandle() )
{
BITMAP bitmap;
m_pCurDrawItemMsg->ItemBitmap.GetBitmap(&bitmap);

int nwidth = bitmap.bmWidth+m_nCellWidth;
rect.left += nwidth;
rect.right+= nwidth;
}

CString strText = GetItemText( hItem );

//这个方法太别扭.因为发现DrawText DT_VCENTER在vc6下无效
CSize sz = pDc->GetTextExtent(strText);
rect.DeflateRect( 0,1,0,1 );
rect.top += (rect.Height()-sz.cy)/2;
rect.right= m_rect.right;

//设置字体
CFont* pOldFont = NULL;
HTREEITEM hParentItem = GetParentItem(hItem);
if ( hParentItem )
{
pOldFont = pDc->SelectObject(&m_FontChild);
}
else
{
pOldFont = pDc->SelectObject(&m_FontRoots);
}

pDc->SetBkMode(TRANSPARENT);
if ( bselected )
{
if ( IsEnableRootBk() )
{
pDc->SetTextColor( m_clrTextSelect );
}
}
else
{
pDc->SetTextColor( m_clrTextNormal );
}


pDc->DrawText(strText, rect, DT_LEFT|DT_TOP);

pDc->SelectObject(pOldFont);
pOldFont = NULL;
}


void CTreeCtrlBT::EnableRowLine(BOOL bEnable /* = TRUE  */)
{
m_bEnableRowLine = bEnable;
}


BOOL CTreeCtrlBT::IsEnableRowLine()
{
return m_bEnableRowLine;
}


void CTreeCtrlBT::EnableRootBk(BOOL bEnable /* = TRUE  */)
{
m_bEnableRootBk = bEnable;
}


BOOL CTreeCtrlBT::IsEnableRootBk()
{
return m_bEnableRootBk;
}


BOOL CTreeCtrlBT::SetBackgroudBitmap(UINT nID )
{
return m_bmpBackgroud.LoadBitmap(nID);
}


BOOL CTreeCtrlBT::SetBackgroudBitmap(LPCTSTR lpszRecourceName)
{
return m_bmpBackgroud.LoadBitmap(lpszRecourceName);
}


void CTreeCtrlBT::SetItemBitmap(HTREEITEM hItem,UINT nIdBitmap)
{
if ( !hItem )
{
return;
}
ITEM_MSG* pItemMsg = GetItemMsg(hItem);
if ( !pItemMsg )
{
return;
}


if ( pItemMsg->ItemBitmap.GetSafeHandle() )
{
pItemMsg->ItemBitmap.DeleteObject();
}

if ( 0 != nIdBitmap )
{
pItemMsg->ItemBitmap.LoadBitmap(nIdBitmap);
}


}


void CTreeCtrlBT::SetItemBitmap(HTREEITEM hItem, LPCTSTR lpszBitmap)
{
if ( !hItem )
{
return;
}
ITEM_MSG* pItemMsg = GetItemMsg(hItem);
if ( !pItemMsg )
{
return;
}

if ( pItemMsg->ItemBitmap.GetSafeHandle() )
{
pItemMsg->ItemBitmap.DeleteObject();
}

CFileFind fileFind;
if ( fileFind.FindFile(lpszBitmap) )
{
pItemMsg->ItemBitmap.LoadBitmap(lpszBitmap);
}
}




/************************************************************************/


/* 函数功能: 设置展开收缩的图表


  /* 函数参数: 
UINT  nIdExpand 展开时候的图标,比如 " - "
UINT      nIdCollapse       收缩时候的图标,比如 " + "
COLORREF  crTransparent 位图透明色

 /* 函数说明:
 两个位图的透明色必须相同,大小必须相同
 
/************************************************************************/
void CTreeCtrlBT::SetExpandBitmap(UINT nIdExpand, UINT nIdCollapse, COLORREF crTransparent /* = RGB */)
{
CBitmap bmpExpand,bmpCollapse;
bmpExpand.LoadBitmap(nIdExpand);
bmpCollapse.LoadBitmap(nIdCollapse);
if ( !bmpExpand.GetSafeHandle() || !bmpCollapse.GetSafeHandle() )
{
return;
}

//保存位图高度//宽度,在绘制的时候居中
BITMAP bitmapExpand,bitmapCollapse;
bmpExpand.GetBitmap(&bitmapExpand);
bmpCollapse.GetBitmap(&bitmapCollapse);
if ( (bitmapExpand.bmWidth  != bitmapCollapse.bmWidth) || 
(bitmapExpand.bmHeight != bitmapCollapse.bmHeight) )
{
return;
}
m_nImageWidth  = bitmapExpand.bmWidth;
m_nImageHeight = bitmapExpand.bmHeight;

//创建CImageList
m_ImageList.Create(11,11,ILC_COLOR24|ILC_MASK,0,2);
m_ImageList.Add(&bmpExpand,crTransparent);
m_ImageList.Add(&bmpCollapse,crTransparent);


bmpExpand.DeleteObject();
bmpCollapse.DeleteObject();
}


/************************************************************************/


/* 函数功能: 插入新的一项


  /* 函数参数: 
HTREEITEM hParent 父节点句柄
LPCTSTR  lpszItem 插入项文本
UINT      nIdBitmap 插入项位图
COLORREF  crTransparent 位图透明色

 /* 函数说明:
 返回插入项的句柄
 
/************************************************************************/
HTREEITEM CTreeCtrlBT::InsertItemEx(HTREEITEM hParent, LPCTSTR lpszItem, UINT nIdBitmap /* = 0 */,COLORREF crTransparent /* = RGB */)
{
HTREEITEM hItem = InsertItem(lpszItem,0,1,hParent);


ITEM_MSG *pItemMsg = new ITEM_MSG;

pItemMsg->hItem = hItem;

if ( 0 != nIdBitmap)
{
pItemMsg->ItemBitmap.LoadBitmap(nIdBitmap);
}


if (pItemMsg->ItemBitmap.GetSafeHandle())
{
pItemMsg->crTransparent = crTransparent;
}

ITEMMSG_MAP::iterator item = m_itmemsg_map.find(hItem);
if ( item == m_itmemsg_map.end() )
{
m_itmemsg_map[hItem] = pItemMsg;
}
else
{
item->second = pItemMsg;
}


return hItem;
}


HTREEITEM CTreeCtrlBT::InsertItemEx(HTREEITEM hParent, LPCTSTR lpszItem, LPCTSTR lpszBitmap,COLORREF crTransparent /* = RGB */)
{
HTREEITEM hItem = InsertItem(lpszItem,0,1,hParent);

CFileFind fileFind;
if ( fileFind.FindFile(lpszBitmap) )
{
ITEM_MSG *pItemMsg = new ITEM_MSG;

pItemMsg->hItem = hItem;

pItemMsg->ItemBitmap.LoadBitmap(lpszBitmap);
if (pItemMsg->ItemBitmap.GetSafeHandle())
{
pItemMsg->crTransparent = crTransparent;
}

ITEMMSG_MAP::iterator item = m_itmemsg_map.find(hItem);
if ( item == m_itmemsg_map.end() )
{
m_itmemsg_map[hItem] = pItemMsg;
}
else
{
item->second = pItemMsg;
}
}

fileFind.Close();

return hItem;
}


void CTreeCtrlBT::OnMouseMove(UINT nFlags, CPoint point) 
{
// TODO: Add your message handler code here and/or call default
CTreeCtrl::OnMouseMove(nFlags, point);


m_ptOldMouse = point;
HTREEITEM hItem = HitTest(point);
if ( hItem != NULL && hItem != m_hItemMouseMove )
{
m_hItemMouseMove = hItem;
Invalidate(FALSE);
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值