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);
}