MFCCListCtrl 图片列表并添加背景图片

MFC CListCtrl 显示图片模式需要关联CImageList,并且增加背景图片(抓狂三天,比网上自绘完美)

头文件定义

CImageList* ListImages;
CListCtrl *ListIcons;

CPP 初始化列表

CRect rect;
	GetClientRect(&rect);
	rect.left = 0; //zp 20160930
	rect.top = LOGO_HEIGHT + 33;
	rect.left = 99;//((rect.Width() - 20) - ((rect.Width() - 20) / mImageWidth)*mImageWidth)/2; // 20 滚动条宽度

	ListIcons = new CListCtrl[1]; // +1表示搜索功能列表

	ListImages = new CImageList[1];

	multiset<VehicleGroup>::iterator itr = mVehicleGroups.begin();

	for(int i = 0; i < 1; i++)
	{
		if () //需要在图片下显示文字
		{
			mImageWidth = 200;
			mImageHeight = 140;
		}
		else // 文字显示在图片上
		{
			mImageWidth = 346;
			mImageHeight = 278;
		}

		//ListIcons[i].Create(WS_CHILD, rect, this, IDC_LIST_ICON);

		//LVS_ALIGNMASK 列表对齐方式,上对齐是上下滚动,左对齐或者右对齐是左右滚动
		ListIcons[i].CreateEx(WS_CHILD, LVS_EX_DOUBLEBUFFER | LVS_AUTOARRANGE | LVS_NOLABELWRAP | LVS_SHAREIMAGELISTS | LVS_SINGLESEL, rect, this, IDC_LIST_ICON);
		ListIcons[i].SetExtendedStyle(LVS_EX_DOUBLEBUFFER );
		ListIcons[i].SetIconSpacing(mImageWidth + 80, mImageHeight + 50); // 图片宽度 + 间距
		ListIcons[i].SetFont(CRunEnvironment::Instance()->TitleFont);

		ListImages[i].Create(mImageWidth, mImageHeight, ILC_COLOR32 | ILC_MASK, 0, 0);
		ListImages[i].SetBkColor(CLR_NONE);

		ListIcons[i].SetImageList(&ListImages[i], LVSIL_NORMAL);     //CImageList associates CListCtrl
		ListIcons[i].SetBkColor(CLR_NONE);
		ListIcons[i].SetTextBkColor(CLR_NONE);
		ListIcons[i].SetTextColor(ColorBlack);

		CBitmap bmp;
		bmp.LoadBitmap(IDB_BITMAP_SHOWCARLIST_BG);
		HBITMAP hBmp = (HBITMAP)bmp;
		ListIcons[i].SetBkColor(ColorWhite); // 必须加上此方法,否则界面滚动会闪烁(此处很重要,抓狂1天)
		ListIcons[i].SetBkImage(hBmp); // 加上之后滚动刷新不出出问题

		ListIcons[i].DeleteAllItems();

增加图片

/*
listIdx 指的是第几个列表,我的工程需要5个列表首先初始化好,切换是直接ShowWindow()
path 图片路径
图片下需要显示的标题
*/
void CVehiclesDlg::Add(int listIdx, CString path, CString name)
{
	///中文和繁体中文,仍然按之前的图片;其他的语言重新绘制
	Bitmap bmp(path);                       //传入图片路径
	Bitmap* pThumbnail = (Bitmap*)bmp.GetThumbnailImage(mImageWidth, mImageHeight, NULL, NULL); //设定缩略图的大小
	if (pThumbnail == NULL)
	{
		return;
	}

	HBITMAP hBmp;
	pThumbnail->GetHBITMAP(Color(255,255,255,255),&hBmp);
	CBitmap *pImage = CBitmap::FromHandle(hBmp); //转换成CBitmap格式位图

	for(int i = 0 ; i < 5; i++)
	{
		int index = ListImages[listIdx].Add(pImage,RGB(255, 255, 255));
		if(index > -1)
		{
			int item = ListIcons[listIdx].InsertItem(index, name, index); //名字会显示在图片下
			break;
		}
	}
}
/*
图片上显示标题
IDC_LIST_ICON 是列表控件ID
#define	IDC_LIST_ICON		        4000
*/
void CVehiclesDlg::AddVehicleOtherLanguage(int listIdx, CString path, CString name)
{
	CRect lpRec;
	//GetDlgItem(IDC_BUTTON_SAVEBMP)->GetClientRect(lpRec);//以自身为起点得到坐标
	GetDlgItem(IDC_LIST_ICON)->GetWindowRect(&lpRec);//以父窗口为起点得到坐标
	ScreenToClient(&lpRec);

	CWindowDC dc(GetDlgItem(IDC_LIST_ICON));
	CBitmap myBitmap;
	CDC myDC;
	myDC.CreateCompatibleDC(&dc);
	myBitmap.CreateCompatibleBitmap(&dc, mImageWidth, mImageWidth); 
	CBitmap *pOldBitmap = myDC.SelectObject(&myBitmap); 
	CRect rc(0, 0, mImageWidth, mImageHeight);
	//添加 PNG 图片
	CGraphic::Instance().LoadPng(&myDC, IDB_PNG_VEHICLE_BTN, rc);

	//计算字体像素高度和宽度
	myDC.SelectObject(CRunEnvironment::Instance()->DiagFont);  // 字体大小
	CSize sz = CGraphic::Instance().GetTextWidth(&myDC, name, CRunEnvironment::Instance()->Instance()->DiagFont);
	CGraphic::Instance().DrawText(&myDC, name, CRunEnvironment::Instance()->GetFontStyleByLang(), CRunEnvironment::Instance()->DiagFont, 0, rc);

	myDC.SelectObject(pOldBitmap); 

	for(int i = 0 ; i < 5; i++)
	{
		int index =ListImages[listIdx].Add(&myBitmap, 255);
		if (-1 < index)
		{
			int item = ListIcons[listIdx].InsertItem(index, _T(""), index); // 名字会显示在图片下
			break;
		}
	}

	ReleaseDC(&dc);
	myDC.DeleteDC();
}

自己动手封装的GDI

#pragma once

#ifndef _GRAPHIC_H__
#define _GRAPHIC_H__

#include <vector>

using namespace std;

class Alignment
{
public:

	typedef enum{
		Unknown = -1,
		TOP = 1,
		LEFT = 2,
		RIGHT = 3,
		BOTTOM = 4,
		CENTER = 5,

		Max
	}Type;

	Alignment::Type mHor;
	Alignment::Type mVer;

	Alignment()
	{
		mHor = CENTER;
		mVer = CENTER;
	}

	Alignment(Alignment::Type hor, Alignment::Type ver)
	{
		mHor = hor;
		mVer = ver;
	}
	virtual ~Alignment(){}


};


class CGraphic
{
public:
	static CGraphic& Instance();

	virtual ~CGraphic();

private:
	static CGraphic* mInstacne;
	CGraphic();

public:
	/**
	 * 函数说明:计算字符串所占宽度,通过给定的字体和宽度进行格式化,返回宽、高,此函数计算使用的函数是 DrawText
	 * 输入参数:CDC *pDC						:上下文指针
	 *			CFont *font						:字体
	 *			CRect &rect						:区域
	 *			CString content					:字符串
	 * 输出参数:CRect &rect					:输出计算后字符串所占区域
	 * 返回值:	返回宽高
	 */
	static CSize CalcText(CDC *pDC, CFont *font, CRect &rect, CString content);

	/**
	 * 函数说明:计算字符串所占宽高,通过给定的字体进行格式化,返回宽、高。此函数计算使用的函数是 GetTextExtent
	 * 输入参数:CDC *pDC						:上下文指针
	 *			CFont *font						:字体
	 *			CString content					:字符串
	 * 返回值:	返回宽高
	 */
	static CSize CalcText(CDC *pDC, CFont *font, CString content);

	/**
	 * 函数说明:计算字符串组中最大宽高,通过给定的字体进行格式化,返回最大宽、高。此函数计算使用的函数是 GetTextExtent
	 * 输入参数:CDC *pDC						:上下文指针
	 *			CFont *font						:字体
	 *			vector<CString> content			:字符串组
	 * 返回值:	返回宽高
	 */
	static CSize CalcText(CDC *pDC, CFont *font, vector<CString> content);

public:

	/**
	 * 函数名称:
	 * 函数说明:
	 * 输入参数:
	 * 输出参数:
	 * 返 回 值:
	 */
	void SetAlignment(Alignment *align);

	/**
	 * 函数说明:
	 * 输入参数:CDC* pDC, CString content, CFont* font, int suppose
	 * 输出参数:
	 * 返回值:
	 */
	CSize GetTextWidth(CDC* pDC, CString content, CFont* font);

	CSize GetTextWidth(CDC *pDC, CString content, CString fontStyle, CFont *fontheight,  CRect &rect);

	/**
	 * 函数说明:
	 * 输入参数:
	 * 输出参数:
	 * 返回值:无
	 */
	void DrawText(CDC *pDC, CString content, CString fontStyle, CFont *fontheight, UINT color,  CRect &rect);

	/************************************************************************
	* 函数说明:加载图片
	* 输入参数:UINT id				:图片ID
	* 输出参数:无
	* 返回值:图片大小
	************************************************************************/
	CSize GetImageSize(UINT id);

	Image* GetPngStream(UINT id);
	void ShowJPGPic(CDC *pDC, UINT nID,CPoint p, CSize sz);

	/**
	 * 函数说明:加载PNG格式的图片到CDC内存中
	 * 输入参数:CDC*pDC							:绘图CDC
	 *			UINT id								:图片资源ID
	 *			CRect &rect							:输入可绘制区域
	 *			, BOOL scaling						:是否缩放
	 * 输出参数:CRect &rect						居中后的图片起始位置
	 * 返回值:无
	 */
	void LoadPng(CDC*pDC, UINT id, CRect &rect, BOOL scaling = FALSE);

private:
	Image* mImage;

	Alignment mAlignment;
};


#endif
#include "StdAfx.h"
#include <Controls/Graphic.h>


CGraphic* CGraphic::mInstacne = NULL;

CGraphic& CGraphic::Instance()
{
	if (NULL == mInst
	acne)
	{
		mInstacne = new CGraphic();
	}
	return *mInstacne;
}

CGraphic::CGraphic()
{
	mImage = NULL;
}

CGraphic::~CGraphic()
{
	if (NULL != mImage)
	{
		delete mImage;
		mImage = NULL;
	}
}

CSize CGraphic::CalcText(CDC *pDC, CFont *font, CRect &rect, CString content)
{
	int iCy = pDC->DrawText(content,&rect,DT_LEFT|DT_EDITCONTROL|DT_WORDBREAK|DT_CALCRECT);

	return CSize(rect.Width(), rect.Height());
}

CSize CGraphic::CalcText(CDC *pDC, CFont *font, CString content)
{
	pDC->SelectObject(font);
	CSize szMax = pDC->GetTextExtent(content);

	return szMax;
}

CSize CGraphic::CalcText(CDC *pDC, CFont *font, vector<CString> content)
{
	pDC->SelectObject(font);
	CSize maxSize(0,0);
	for (UINT i = 0; i < content.size(); i++)
	{
		CSize szMax = pDC->GetTextExtent(content[i]);
		if (maxSize.cx < szMax.cx)
		{
			maxSize.cx = szMax.cx;
		}
		if (maxSize.cy < szMax.cy)
		{
			maxSize.cy = szMax.cy;
		}
	}
	return maxSize;
}


Image* CGraphic::GetPngStream(UINT uiID)
{
	HINSTANCE hInst = AfxGetResourceHandle();

	HRSRC hRsrc = ::FindResource (hInst,MAKEINTRESOURCE(uiID),_T("PNG")); // type
	if (!hRsrc)
	{
		return NULL;
	}

	// load resource into memory
	DWORD len = SizeofResource(hInst, hRsrc);
	BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);
	if (!lpRsrc)
	{
		return NULL;
	}

	// Allocate global memory on which to create stream
	HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
	BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
	memcpy(pmem,lpRsrc,len);
	IStream* pstm;
	CreateStreamOnHGlobal(m_hMem,FALSE,&pstm);

	// load from stream这是关键一句,通过FromStream返回以各Image*,然后在Graphic的DrawImage地方调用就行了!
	Image* pImg = Gdiplus::Image::FromStream(pstm);

	// free/release stuff
	GlobalUnlock(m_hMem);
	pstm->Release();
	FreeResource(lpRsrc);

	return pImg;
}

CSize CGraphic::GetImageSize(UINT id)
{
	mImage = GetPngStream(id);

	return CSize(mImage->GetWidth(), mImage->GetHeight());
}

void CGraphic::SetAlignment(Alignment *align)
{
	mAlignment = *align;
}

void CGraphic::LoadPng(CDC*pDC, UINT id, CRect &rect, BOOL scaling)
{
	CSize img = GetImageSize(id);

	Graphics graphics(pDC->m_hDC);

	if (scaling)
	{
		// 让其平铺拉伸(默认为渐变拉伸)
		ImageAttributes imgAtt;
		imgAtt.SetWrapMode(WrapModeTileFlipXY);
		RectF rcDrawRect;
		rcDrawRect.X=rect.left;
		rcDrawRect.Y=rect.top;
		rcDrawRect.Width=rect.right - rect.left;
		rcDrawRect.Height=mImage->GetHeight();
		graphics.DrawImage(mImage, rcDrawRect, 0, 0, mImage->GetWidth(), mImage->GetHeight(), UnitPixel, &imgAtt, NULL, NULL);
	}
	else
	{
		if (Alignment::LEFT == mAlignment.mHor)
		{
		}
		else if (Alignment::RIGHT == mAlignment.mHor)
		{
			rect.left += rect.Width() - img.cx;
		}
		else
		{
			rect.left += (rect.Width() - img.cx)/2;
		}
		rect.right = rect.left + img.cx;
		
		if (Alignment::TOP == mAlignment.mVer)
		{
		}
		else if (Alignment::BOTTOM == mAlignment.mVer)
		{
			rect.top += rect.Height() - img.cy;
		}
		else
		{
			rect.top += (rect.Height() - img.cy)/2;
		}
		rect.bottom = rect.top + img.cy;
		
		graphics.DrawImage(mImage, rect.left, rect.top, img.cx, img.cy);
	}
}

void CGraphic::DrawText(CDC *pDC, CString content, CString fontStyle, CFont *fontheight,  UINT color, CRect &rect)
{
	Graphics graphics(pDC->m_hDC);

	graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);

	WCHAR fs[1024] = {0x00};
	wcscpy_s(fs, 1024, CT2CW(fontStyle));              //如果使用MFC中的CString,需要这样转换成WCHAR

	FontFamily fontFamily(fs);

	LOGFONT *lf = new LOGFONT;
	fontheight->GetLogFont(lf);
	Gdiplus::Font myFont(&fontFamily, lf->lfHeight, FontStyleBold, UnitPoint); //第二个是字体大小

	RectF outRect;
	graphics.MeasureString(content, content.GetLength(), &myFont, RectF(rect.left, rect.top, rect.Width(), rect.Height()), &outRect);

	UINT r = (color>>16)&0xff;
	UINT g = (color>>8)&0xff;
	UINT b = color&0xff;

	SolidBrush blackBrush(Color(255, r, g, b));  //半透明+文字RGB颜色
	StringFormat format;
	format.SetAlignment(StringAlignmentCenter);    //文本排列方式,即在对应位置居中、靠左、靠右

	RectF rc = RectF(rect.left, rect.top + (rect.Height() - outRect.Height)/2, rect.Width(), outRect.Height);
	graphics.DrawString(content, content.GetLength(), &myFont, rc, &format, &blackBrush );//把string绘制到图上
}

void CGraphic::ShowJPGPic(CDC *pDC, UINT nID,CPoint p, CSize sz)
{
	HINSTANCE hInst = AfxGetResourceHandle();
	HRSRC hRsrc = ::FindResource(hInst,MAKEINTRESOURCE(nID),_T("JPG")); // type
	if (!hRsrc)
		return;

	// load resource into memory
	DWORD len = SizeofResource(hInst, hRsrc);
	BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);
	if (!lpRsrc)
		return;

	IPicture  *pPic = NULL;
	IStream   *pStm = NULL;
	//分配全局存储空间  
	HGLOBAL hGlobal=GlobalAlloc(GMEM_FIXED,len);  
	if(hGlobal==NULL)
		return;  

	BYTE*  pvData = (BYTE*)GlobalLock(hGlobal);  
	if(pvData==NULL)//锁定分配内存块  
	{
		GlobalFree(hGlobal);
		return;
	}

	memcpy(pvData,lpRsrc,len);
	GlobalUnlock(hGlobal);
	CreateStreamOnHGlobal(hGlobal,TRUE,&pStm);  

	//装入图形文件  
	OleLoadPicture(pStm,len,TRUE,IID_IPicture,(LPVOID*)&pPic);  
	pStm->Release();
	pStm = NULL;
	GlobalFree(hGlobal);

	if(NULL == pPic)return;

	long   hmWidth;//图片的真实宽度  
	long   hmHeight;//图片的真实高度  
	pPic->get_Width(&hmWidth);  
	pPic->get_Height(&hmHeight);  

	//将图形输出到屏幕上(有点像BitBlt)  
	pPic->Render(pDC->m_hDC, p.x, p.y, sz.cx, sz.cy, 0, hmHeight, hmWidth, -hmHeight, NULL);  
	pPic->Release();  
}

CSize CGraphic::GetTextWidth(CDC* pDC, CString content, CFont* font)
{
	pDC->SelectObject(font);
	CSize sz = pDC->GetTextExtent(content);

	return sz;
}

CSize CGraphic::GetTextWidth(CDC *pDC, CString content, CString fontStyle, CFont *fontheight,  CRect &rect)
{
	Graphics graphics(pDC->m_hDC);

	graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);

	LOGFONT *lf = new LOGFONT;
	fontheight->GetLogFont(lf);
	WCHAR fs[1024] = {0x00};
	wcscpy_s(fs, 1024, CT2CW(fontStyle));              //如果使用MFC中的CString,需要这样转换成WCHAR

	FontFamily fontFamily(lf->lfFaceName);

	Gdiplus::Font myFont(&fontFamily, lf->lfHeight, FontStyleBold, UnitPoint); //第二个是字体大小

	RectF outRect;
	graphics.MeasureString(content, content.GetLength(), &myFont, RectF(rect.left, rect.top, rect.Width(), rect.Height()), &outRect);

	rect.left = outRect.X;
	rect.right = rect.left + outRect.Width;
	rect.top = outRect.Y;
	rect.bottom = rect.top + outRect.Height;

	return CSize(outRect.Width, outRect.Height);
}


  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值