Chinaunix首页 | 论坛 | 博客
  • 博客访问: 588330
  • 博文数量: 752
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 5005
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:47
文章分类

全部博文(752)

文章存档

2011年(1)

2008年(751)

我的朋友

分类:

2008-10-13 16:55:12

如何在树型控件中使用背景位图
作者:


一、引言:
对于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---------------------

阅读(1084) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~