CTreeCtrl中使用CxImage添加背景图片,以及给字添加背景图片

在CTreeCtrl中加载背景图片,网上有很多例子,有的可行有的不行,这两天一边看资料一边整理,自己写了一个用CxImage加载图片的方法,大家可以参考下。有的地方还没有完善,不过基本功能可以实现,而且添加图片后屏幕不闪烁。已经试过了。

SetReDraw():保证其不要在子节点弹出时重画,而是在子节点已经扩展后重画

在做程序时,遇到了一个很白痴的问题,就是我想要实现鼠标滚动消息时,写了之后调试代码进不去,经过我查看,把ON_WM_MOUSEWHELL放到前面就可以了

(一)使用CxImage可以添加任意的图片

1、在.h中添加静态库

#include "ximage.h"
#pragma comment(lib,"cximage.lib")
#pragma comment(lib,"Jpeg.lib")
#pragma comment(lib,"png.lib")
#pragma comment(lib,"zlib.lib")

2、并且声明两个关于CxImage的变量,用来存放背景图片

CxImage *m_TreeBkImage;
//TreeCtrl的背景图片

CxImage *m_Text
BkImage; //字的背景图片

3、定义消息防止屏幕闪烁

afx_msg BOOL OnEraseBkgnd(CDC *pDC);

afx_msg void OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult);

afx_msg void OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult);

(二)在.cpp中初始化定义的变量

m_TreeBkImage = new CxImage(); //图片背景

m_TextBkImage = new CxImage(); //字的背景

ON_WM_ERASEBKGND()

ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING,OnItemexpanding)

ON_NOTIFY_REFLECT(TVN_ITEMEXPANDED,OnItemexpanded)

1、在OnPaint()调用整体的图片、字体等

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

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

	DrawBack(&MemeDc);
	DrawItem(&MemeDc);

2、画图片背景

void UITreeCtrl::DrawBack(CDC* pDC)
{
	if(m_IsDrawBack == TRUE)
	{
		m_LoadDC.CreateCompatibleDC(NULL);//创建兼容DC
		m_LoadDC.SelectObject(&m_bitmap);//将兼容位图选入兼容DC,
		m_LoadDC.FillSolidRect(&m_ClientRect,RGB(255,255,255));//首先将bakeBitmap(客户区)填充成背景颜色,这里用的是白色。

		PaintImage(pDC,&m_ClientRect,&m_LoadDC);
		m_LoadDC.DeleteDC();
	}
	else
		pDC->FillSolidRect(&m_ClientRect,m_TreeBkcolor);
}

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

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

3、重绘每一项

void UITreeCtrl::DrawItem(CDC* pDc)
{
	HTREEITEM currentItem,parentItem;//当前的句柄,和它的父节点的句柄
	DWORD    treeStyle;// 数的类型
	CRect    itemRect;//每一项的区域
	int      itemState;//某项的状态
	currentItem = GetFirstVisibleItem();//获取第一个课可见的项
	do
	{
		if (GetItemRect(currentItem,itemRect,TRUE))
		{
			itemRect.left=itemRect.left-15;

			CRect   fillRect(0,itemRect.top,m_ClientRect.right,itemRect.bottom);
			itemState = GetItemState(currentItem,TVIF_STATE);

			if (itemRect.top>m_ClientRect.bottom)  //说明这一项已超出窗口的边界,所以不绘制
				break;

			DrawItemText(pDc,currentItem,itemRect);
		}
	} while ((currentItem=GetNextVisibleItem(currentItem)) != NULL);
}

4、重绘字体以及”+“”-“连线

void UITreeCtrl::DrawItemText(CDC * pDc,HTREEITEM hItem,CRect  pRect)
{
	int    itemState;//某项的状态
	DWORD  dwStyle = GetStyle();
	CRect  rcItem,rcTemp,SelRect;//文字位置
	CPoint ptTemp;
	UINT   indent = GetIndent();
	SelRect = pRect;
	SelRect.left += 15;

	pDc->SelectObject(&m_font);	//字的大小
	itemState = GetItemState(hItem,CDIS_SELECTED);
 	if(itemState &TVIS_SELECTED)	//选中时的背景颜色和字体颜色改变
	{
 		pDc->SetTextColor(m_STextcolor);
 		DrawTextImage(pDc,&SelRect);
 	}
 	else
		pDc->SetTextColor(m_textcolor);
	CString ItemText = GetItemText(hItem);
	CSize  fontSize;
	fontSize= pDc->GetTextExtent(ItemText);

	rcTemp		 = pRect;
	rcTemp.left += 18;
	rcTemp.top  += 2;

	pDc->SetBkMode(TRANSPARENT);
	pDc->DrawText(ItemText,rcTemp,DT_LEFT|DT_TOP);//显示项文本

	GetItemRect(hItem,&rcItem,TRUE);	//取得Item的文本矩形范围
	//2、如果要画线
	if(dwStyle & TVS_HASLINES)
	{
		//创建一个真正的点线画笔
		LOGBRUSH logBrush;
		logBrush.lbColor = m_textcolor;
		logBrush.lbStyle = BS_SOLID;
		CPen pen(PS_COSMETIC | PS_ALTERNATE, 1, &logBrush);
		CPen* oldPen = pDc->SelectObject(&pen);  

		rcTemp = rcItem;
		rcTemp.left -= indent;//从当前向左移动一个 缩进 的量
		rcTemp.right = rcTemp.left + indent;
		ptTemp = rcTemp.CenterPoint();  

		//如果 Item 有父 Item 则在自己面前画一个'L'型的线,拐点正是缩进矩形的中心点
		if( GetParentItem(hItem) != NULL )
		{
			//如果 Item 有一个弟弟节点(哥哥排上面), 则在自己面前画一条竖线, 否则画半条
			pDc->MoveTo( ptTemp.x - 1,rcTemp.top - 1 );
			if(GetNextSiblingItem(hItem) != NULL)
				pDc->LineTo( ptTemp.x - 1, rcTemp.bottom );
			else
				pDc->LineTo( ptTemp.x - 1, ptTemp.y - 1 );
			pDc->MoveTo( rcTemp.right, ptTemp.y - 1 );
			pDc->LineTo( ptTemp.x - 1, ptTemp.y - 1 );
		}
		//依次绘制各个 Item 的父节点与叔叔节点之间被撑开的部分的连线
		HTREEITEM hItemTemp = hItem;
		while( hItemTemp = GetParentItem(hItemTemp) )
		{
			rcTemp.OffsetRect(-indent, 0);
			ptTemp = rcTemp.CenterPoint();
			if(GetNextSiblingItem(hItemTemp))
			{
				pDc->MoveTo( ptTemp.x - 1, rcTemp.top );
				pDc->LineTo( ptTemp.x - 1, rcTemp.bottom );
			}
		}
		//显示删除 MFC GDI 对象, 因为以前版本的 MFC 貌似有个BUG, 如果你不显示删除它就不会帮你删除, 这个BUG好像还存在
		pDc->SelectObject(oldPen);
		pen.DeleteObject();
		pen.DeleteTempMap();
	}  

	//3、绘制小'+'框
	if(dwStyle & TVS_HASBUTTONS)
	{
		rcItem.left -= indent;
		rcItem.right = rcItem.left + indent;
		//确定绘制范围
		rcTemp.SetRect(0, 0, 9, 9);
		rcTemp.OffsetRect(rcItem.CenterPoint());
		rcTemp.OffsetRect(-5, -5);
		//绘制, 因为使用的是MFC10.0, 因此实际绘制工作可交给 CMFCVisualManager 完成,其实... 自己画难度也不大
		if( ItemHasChildren(hItem) )
			CMFCVisualManager::GetInstance()->OnDrawExpandingBox(pDc, rcTemp, ( GetItemState(hItem, TVIS_EXPANDED) & TVIS_EXPANDED ?TRUE:FALSE), RGB(0, 0, 0));
	}  

}

5、从本地加载图片需要知道图片的路径,定义函数专门加载图片的路径

CString UITreeCtrl::ReturnPicLoad()
{
	//定义路径
	CString path;	//获取系统参数
	GetModuleFileName(NULL,path.GetBufferSetLength(MAX_PATH+1),MAX_PATH);
	path.ReleaseBuffer();
	int pos = path.ReverseFind('\\');
	m_exePath = path.Left(pos+1);
	return m_exePath;
}

6、知道了图片的路径才能加载图片,如果路径不正确,则没有图片出现

void UITreeCtrl::AddLoadPicture(CString pSrc)
{
	if(pPic == pSrc)	return;
	else	m_IsDrawBack = TRUE;

	pPic    = pSrc;
	m_TreeBkImage->Load(m_exePath+pPic,FindType(pPic));
	m_TreeBkImage->Draw(pDC->GetSafeHdc(),pRect->left,pRect->top,pRect->Width(),pRect->Height(),0,true);
	pDC->BitBlt(pRect->left,pRect->top,pRect->Width(),pRect->Height(),pSrc,0,0,SRCCOPY);
}

7、在程序运行过程中会出现闪烁问题,虽然网上有很多解决方式大同小异,但是还是想写下,这样比较代码比较完善

void UITreeCtrl::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult)
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	SetRedraw(FALSE);
	*pResult = 0;
}
void UITreeCtrl::OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult)
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	Invalidate();
	SetRedraw(TRUE);
	*pResult = 0;
}

8、很多朋友看到上面那个FindType这个函数没有定义 ,这个主要是根据加载的图片可以找到图片的后缀类型

int UITreeCtrl::FindType(CString filename)
{
	//根据图片找到图片的后缀类型
	CString ext = filename.Right(filename.GetLength()-filename.ReverseFind('.')-1);
	int type = 0;
	if (ext == _T("bmp"))	type = CXIMAGE_FORMAT_BMP;
#if CXIMAGE_SUPPORT_JPG
	else if (ext == _T("jpg") || ext == _T("jpeg"))  type = CXIMAGE_FORMAT_JPG;
#endif
#if CXIMAGE_SUPPORT_GIF
	else if (ext == _T("gif"))	 type = CXIMAGE_FORMAT_GIF;
#endif
 #if CXIMAGE_SUPPORT_PNG
 	else if (ext == _T("png"))    type = CXIMAGE_FORMAT_PNG;
 #endif
	else type = CXIMAGE_FORMAT_MNG;
<span style="white-space: pre;">	</span>return type;<span style="white-space: pre;">	</span>
}
BOOL UITreeCtrl::OnEraseBkgnd(CDC *pDC)
{
	return true;
}

最核心的内容就是上面的了

下面我再介绍一种方式,可以重绘TreeCtrl的这两种方式我都试过的。可行。

void UITreeCtrl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
    LPNMTVCUSTOMDRAW pCustomDraw = (LPNMTVCUSTOMDRAW) pNMCD;
	NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );
	HTREEITEM hItem = (HTREEITEM) pLVCD->nmcd.dwItemSpec;
	*pResult  =  CDRF_DODEFAULT;
	CDC     *pDC = CDC::FromHandle(pLVCD->nmcd.hdc);
	switch   (pLVCD-> nmcd.dwDrawStage)
	{
 	case   CDDS_PREPAINT:	    //绘制控件前
 		{
 			*pResult = CDRF_NOTIFYITEMDRAW;
			break;
 		}
	case   CDDS_ITEMPREPAINT:	//	一个项被绘制前
		{
			CRect rcItem(pNMCD->rc);
			rcClient = rcItem;
			CPoint ptItem(rcItem.left + 1, rcItem.top + 1);
			if (!hItem)
				return;
			//画文字、线、"+"号
			DrawItem(hItem,pCustomDraw);
			*pResult = CDRF_SKIPDEFAULT;//告诉系统跳过默认处理
			return;
		}
		break;
	}
}
void UITreeCtrl::DrawItem(HTREEITEM hItem,LPNMTVCUSTOMDRAW  lpNMTVCD)
{
	DWORD dwStyle = GetStyle();
	CRect rcItem,rcTemp;
	CPoint ptTemp;
	UINT indent = GetIndent();
	//取得 Item 文本的矩形范围
	GetItemRect(hItem, &rcItem, TRUE);
	CDC dc;
	dc.Attach(lpNMTVCD->nmcd.hdc);

	if(lpNMTVCD->nmcd.uItemState & CDIS_SELECTED)
	{    //如果 Item 被选中
		dc.SetTextColor(RGB(0,0,255));
		dc.FillSolidRect(&rcItem,m_STextcolor);
	}
	else
	{
		dc.SetTextColor(m_textcolor);
	}
	dc.SetBkMode(TRANSPARENT);
	rcTemp = rcItem;
	rcTemp.left += 2;
	rcTemp.top += 2;
	//1、绘制文本
	dc.DrawText(GetItemText(hItem), &rcTemp, DT_LEFT | DT_SINGLELINE | DT_VCENTER);  

	//2、如果要画线
	if(dwStyle & TVS_HASLINES)
	{
		//创建一个真正的点线画笔
		LOGBRUSH logBrush;
		logBrush.lbColor = m_textcolor;
		logBrush.lbStyle = BS_SOLID;
		CPen pen(PS_COSMETIC | PS_ALTERNATE, 1, &logBrush);
		CPen* oldPen = dc.SelectObject(&pen);  

		rcTemp = rcItem;
		rcTemp.left -= indent;//从当前向左移动一个 缩进 的量
		rcTemp.right = rcTemp.left + indent;
		ptTemp = rcTemp.CenterPoint();  

		//如果 Item 有父 Item 则在自己面前画一个'L'型的线,拐点正是缩进矩形的中心点
		if( GetParentItem(hItem) != NULL )
		{
			//如果 Item 有一个弟弟节点(哥哥排上面), 则在自己面前画一条竖线, 否则画半条
			dc.MoveTo( ptTemp.x - 1,rcTemp.top - 1 );
			if(GetNextSiblingItem(hItem) != NULL)
				dc.LineTo( ptTemp.x - 1, rcTemp.bottom );
			else dc.LineTo( ptTemp.x - 1, ptTemp.y - 1 );
			dc.MoveTo( rcTemp.right, ptTemp.y - 1 );
			dc.LineTo( ptTemp.x - 1, ptTemp.y - 1 );
		}
		//依次绘制各个 Item 的父节点与叔叔节点之间被撑开的部分的连线
		HTREEITEM hItemTemp = hItem;
		while( hItemTemp = GetParentItem(hItemTemp) )
		{
			rcTemp.OffsetRect(-indent, 0);
			ptTemp = rcTemp.CenterPoint();
			if(GetNextSiblingItem(hItemTemp))
			{
				dc.MoveTo( ptTemp.x - 1, rcTemp.top );
				dc.LineTo( ptTemp.x - 1, rcTemp.bottom );
			}
		}
		//显示删除 MFC GDI 对象, 因为以前版本的 MFC 貌似有个BUG, 如果你不显示删除它就不会帮你删除, 这个BUG好像还存在
		dc.SelectObject(oldPen);
		pen.DeleteObject();
		pen.DeleteTempMap();
	}  

	//3、绘制小'+'框
	if(dwStyle & TVS_HASBUTTONS)
	{
		rcItem.left -= indent;
		rcItem.right = rcItem.left + indent;
		//确定绘制范围
		rcTemp.SetRect(0, 0, 9, 9);
		rcTemp.OffsetRect(rcItem.CenterPoint());
		rcTemp.OffsetRect(-5, -5);
		//绘制, 因为使用的是MFC10.0, 因此实际绘制工作可交给 CMFCVisualManager 完成,其实... 自己画难度也不大
		if( ItemHasChildren(hItem) )
			CMFCVisualManager::GetInstance()->OnDrawExpandingBox(&dc, rcTemp, ( GetItemState(hItem, TVIS_EXPANDED) & TVIS_EXPANDED ?TRUE:FALSE), RGB(0, 0, 0));
	}
	//完成
	dc.Detach();

}

时间: 2024-09-30 19:06:11

CTreeCtrl中使用CxImage添加背景图片,以及给字添加背景图片的相关文章

MFC 基础知识:对话框背景添加图片和按钮Button添加图片

很长时间没有接触MFC相关的知识了,我大概是在大二时候学习的MFC相关知识及图像处理,现在由于要帮个朋友完成个基于C++的程序,所以又回顾了下相关知识.的确,任何知识一段时间过后都比较容易忘记,但回顾起来还是很有印象的. 这篇文章主要是回顾以前的MFC基础知识,给对话框添加背景图片和给按钮button添加背景图片:希望此篇基础性文章对大家有所帮助!同时为下次做MFC相关知识提供点此时所想所感吧.内容比较简单,高手飘过~ 一. 对话框背景添加图片 首先通过VS2012创建MFC对话框应用程序,项目

Android 使用ContentProvider扫描手机中的图片,仿微信显示本地图片效果

首先我们先看第一个界面吧,使用将手机中的图片扫描出来,然后根据图片的所在的文件夹将其分类出来,并显示所在文件夹里面的一张图片和文件夹中图片个数,我们根据界面元素(文件夹名, 文件夹图片个数,文件夹中的一张图片)使用一个实体对象ImageBean来封装这三个属性 package com.example.imagescan; /** * GridView的每个item的数据对象 * * @author len * */ public class ImageBean{ /** * 文件夹的第一张图片路

002-UIImageView和UIButton对比 UIImageView的帧动画 格式符补充 加载图片两种方式 添加删除SUBVIEW

一>.UIImageView和UIButton对比 显示图片 1> UIImageView只是一种图片(图片默认会填充整个UIImageView)  image\setImage: 2> UIButton能显示2种图片 * 背景 (背景会填充整个UIButton)  setBackgroundImage:forState: * 前置(覆盖在背景上面的图片,按照之前的尺寸显示)  setImage:forState: * 还能显示文字 点击事件 1> UIImageView默认是不能

Qt:添加点击事件的Label并显示图片

1.给label添加点击事件 Qt中原本的label是没有点击事件的,如果想添加点击事件的话,可以继承QLabel类并重载鼠标事件(比如mousePressedEvent),然后在鼠标事件中发送一个信号,具体如下: // clicklabel.h #ifndef CLICKEDLABEL_H #define CLICKEDLABEL_H #include <QWidget> #include <QLabel> class ClickedLabel : public QLabel {

换主页轮播的主题图片(2、添加)---轻开电子商务系统(企业入门级B2C网站)

接上一博 文件:site/links/img0.html中的添加按钮(第14行) <center><if x="@{sys:canDo}"><a href="@{sys:face}site/links/img0_add.html" x=true>[添加]</a></if></center> 效果 点"[添加]"跳转到文件:site/links/img0_add.html(在轻

开发路程(14):背景图片移动插件MyFloatingBg(浮动背景图效果,可让背景随着页面的滚动而滚动)

MyFloatingBg这插件可以帮助你在网页上加入可移动背景Background.你可以用于整个文件的背景,或是某几个banner的背景. 它可支持简单的animation效果,你不用去做一个flash文件或动态gif图片.单靠jquery和图片,你便可以做出不同的效果.由于我们把动画效果跟内容分开,我们也可以随时更改文字等内容,而不影响其运作.这个效果很是大气,我想可以使用在高级餐厅,珠宝展会等中做展示用. 1 <!doctype html> 2 <html lang="e

一个iOS图片选择器的DEMO(实现图片添加,宫格排列,图片长按删除,以及图片替换等功能)

在开发中,经常用到选择多张图片进行上传或作其他处理等等,以下DEMO满足了此功能中的大部分功能,可直接使用到项目中. 主要功能如下: 1,图片九宫格排列(可自动设置) 2,图片长按抖动(仿苹果软件删除时,图标抖动效果),可进入删除状态,再次单击进入普通状态 3,图片设置最大上限,加号按钮自动隐藏 4,已选图片可单击进行重新选择 5,无需代理,直接调用对应属性就可获取所有图片,并与显示顺序保持一致 效果图如下: 1 // 2 // SZAddImage.h 3 // addImage 4 // 5

从web编辑器 UEditor 中单独提取图片上传,包含多图片单图片上传以及在线涂鸦功能

UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码.(抄的...) UEditor是非常好用的富文本web编辑器,而且全中文API和注释,方便学习和使用.特别是图片上传查看及涂鸦功能极为喜欢,但是有很多情况我们并不需要Web编辑器,而只需要图片上传.那么问题来了,提取图片上传哪家强..... 网上有很多图片上传的控件.插件.但都不是那么的完美,有的只有一张图片上传不包含批量上传,有的没有图片查看

拍照党福利驾到 华为云微认证教你实现图片压缩和水印添加

在手机拍照成为日常的今天,用照片记录生活已成为人们的一种习惯.拍照容易处理难,面对手机相册中大量的照片,你是否也苦恼过?删,舍不得:上传,会不会被盗图?能否发出足够个性的图片称霸朋友圈?不用担心,华为云微认证结合函数工作流服务,教你轻松实现图片压缩和水印添加,让您体验函数工作流带来的高资源利用率和高处理效率,让即便是无照不活的拍照党也再无后顾之忧. 云服务助力图片存储及管理一般而言,我们压缩图片有四种方法:使用图片压缩软件.网页在线图片压缩.自设图片压缩代码.使用云服务批量压缩.水印添加一般也有