如何在树型控件中使用背景位图
作者:
一、引言:
对于TREWVIEW控件的背景位图的实现,目前介绍的文章比较少,有人虽然实现了,但是在点击TREE时,背景闪动比较厉害。本人在参照别人代码的基础上,把它总结一下,同时解决了这个背景闪烁的问题。目前FLASHGET1.3版也实现了TREEVIEW的背景位图。大家可以参照一下。
本文程序运行效果如下图:
二、原理:
因为WINDOWS标准TREEVIEW控件不支持背景位图,所以如果需要设置背景位图就需要先让其在内存CDC对象上对TREEVIEW缺省绘图,然后在选择背景位图,与缺省位图合成,即采用贴图的方式,把标准的TREEVIEW窗口贴在底图上。这个操作在内存中完成。
同时为了避免闪烁,必须重载OnItemexpanding和OnItemexpanded这两个函数。SetRedraw函数主要保证其不要在子树弹出时重画,而是子树已经扩展后重画。
三、实现步骤:
3.1 加入成员函数
BOOL CMyTreeCtrl::SetBKImage(LPCTSTR LpszResource)
{
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;
}
3.2 为WM_PAINT加入消息句柄
void CMyTreeCtrl::OnPaint()
{
CPaintDC dc(this);
CRect rcclient;
GetClientRect(&rcclient);
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,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();
}
3.3 处理tvn_itemexpanding
void CMyTreeCtrl::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
SetRedraw(FALSE);
*pResult = 0;
}
3.4 处理tvn_itemexpanded
void CMyTreeCtrl::OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
Invalidate();
SetRedraw(TRUE);
*pResult = 0;
}
3.5 加入WM_ERASEBKGND消息处理函数
既然我们在OnPaint()函数中处理位图并返回TRUE以保证默认的窗口进程不擦除背景,加入这个消息句柄可以避免额外的对客户区的刷新以减少闪烁。
BOOL CMyTreeCtrl::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
(完)
--------------------next---------------------
我对本站的"轻松实现类VC界面"例程,结合你的方法树控件添加背景位图,可是不成功啊,跟踪调试发现loadImage()获得不到位图句柄hmp,我实在
MainFram::OnCreate()中调用SetBKIamge()的,怎么回事呢?? ( hanbg 发表于 2006-12-5 10:44:00)
有滚动条存在的时候,移动滚动条背景变花了,需要处理WM_VSCROLL和WM_HSCROLL消息。代码如:void CBmpTreeCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
CTreeCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
SetRedraw(TRUE);
} ( waft_xu 发表于 2006-5-16 11:13:00)
OnPaint()函数改进如下,效果比原来好,代码更简单。
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 );
DefWindowProc(WM_PAINT, (WPARAM)memdc.m_hDC , 0);
CDC maskdc;
maskdc.CreateCompatibleDC(&dc);
CBitmap maskbitmap;
maskbitmap.CreateCompatibleBitmap(&dc, rcclient.Width(), rcclient.Height());
maskdc.SelectObject( &maskbitmap );
CBrush brush;
brush.CreatePatternBrush(&m_bitmap);
maskdc.FillRect(rcclient, &brush);
maskdc.BitBlt(0,0,rcclient.Width(), rcclient.Height(),&memdc,0,0,SRCAND);
dc.BitBlt(rcclient.left, rcclient.top, rcclient.Width(), rcclient.Height(),
&maskdc,rcclient.left, rcclient.top,SRCCOPY);
} ( 刚刚先生 发表于 2003-11-24 16:04:00)
大家有没有考虑到有滚动条存在的时候的情况?? ( bluetlck 发表于 2003-7-10 9:52:00)
多谢!我正需要这方面的知识。 ( musicfan 发表于 2003-3-25 21:43:00)
不是说展开时的闪烁,我意思是背景重画处理效果不好 ( flybus 发表于 2003-1-3 16:37:00)
可疯狂提高显示效果,一言难尽 ( flybus 发表于 2003-1-3 16:35:00)
该类不能应用于 FORMVIEW 上的treectrl,当formview放大或大小改变时有大范围的闪烁。 ( asdmusic 发表于 2002-11-12 8:51:00)
InsertItem并展开时有错误,仿佛图象被往下挤了下去。 ( Tom_lyd 发表于 2002-11-6 18:13:00)
CWnd::DefWindowProc(WM_PAINT, (WPARAM)memdc.m_hDC , 0);
看不懂!!!!!
能不能解释一下!谢谢! ( zwcboy 发表于 2002-9-26 15:37:00)
.......................................................
--------------------next---------------------