步骤简要如下:
1. 创建ClmageList 对象,指定图片的宽度和高度
2. 将CImageList 对象传递给CListCtrl 对象
3.ClistCtrl 增加item 时,将图片ID 和文字一起传入
具体代码如下:
ListImage.cpp 代码如下
// ListImage.cpp : implementation file //
#include "stdafx.h" #include "practise.h" #include "ListImage.h" #define THUMWIDTH 75 #define THUMHEIGHT 55
// ListImage dialog
IMPLEMENT_DYNAMIC(ListImage, CDialog)
ListImage::ListImage(CWnd* pParent /*=NULL*/) : CDialog(ListImage::IDD, pParent) {
}
ListImage::~ListImage() { }
void ListImage::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_LIST1, m_List); DDX_Control(pDX, IDC_EDIT2, m_edit2); }
BEGIN_MESSAGE_MAP(ListImage, CDialog) ON_BN_CLICKED(IDC_BUTTON1, &ListImage::OnBnClickedButton1) ON_BN_CLICKED(IDOK, &ListImage::OnBnClickedOk) END_MESSAGE_MAP()
// ListImage message handlers BOOL ListImage::OnInitDialog() { CDialog::OnInitDialog();
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void ListImage::OnBnClickedButton1() { // TODO: Add your control notification handler code here // 文件对话框
CString FilePath; CFileDialog FileDialog(true, _T(""), _T(""), OFN_EXPLORER, _T(" 所有文件(*.*)|*.*||"), this);
// 显示对话框 if(FileDialog.DoModal() == IDOK) { FilePath = FileDialog.GetPathName(); int g=FilePath.ReverseFind('//'); FilePath=FilePath.Left(g+1); m_edit2.SetWindowText(FilePath);
} else { return; } // 清楚m_ImageList 对象和m_List if (m_ImageList!=NULL) { for(int kk=0;kk<m_ImageList.GetImageCount();kk++) m_ImageList.Remove(kk); m_List.DeleteAllItems(); } else { m_ImageList.Create(THUMWIDTH,THUMHEIGHT, ILC_COLORDDB|ILC_MASK, 20, 1); m_List.SetImageList(&m_ImageList, LVSIL_NORMAL); m_List.SetImageList(&m_ImageList, LVSIL_SMALL); } m_List.SetRedraw(false); CString strDir=FilePath+_T("*.*"); //strDir.Format("%s%s",FilePath,L"*.*"); //_T("D://happiness// 风景桌面//*.*"); int i=0,cn=0,j=0; SHFILEINFO finfo; CString fileName; CString filePath2; HANDLE hFind; WIN32_FIND_DATA fd ; hFind=::FindFirstFile((LPCTSTR)strDir,&fd); if(hFind==INVALID_HANDLE_VALUE)return; do { if ( !wcscmp(fd.cFileName, _T(".")) || !wcscmp(fd.cFileName, _T("..")))continue; if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)continue; fileName=fd.cFileName; filePath2=FilePath+fileName; i=fileName.Find(_T(".jpg"),0); // 加载jpg,jpeg,gif 格式的图片 if (i==-1) i=fileName.Find(_T(".jpeg"),0); if (i==-1) i=fileName.Find(_T(".JPG"),0); if (i==-1) i=fileName.Find(_T(".JPEG"),0); if (i==-1) i=fileName.Find(_T(".gif"),0); if (i==-1) i=fileName.Find(_T(".GIF"),0); if (i==-1) i=fileName.Find(_T(".BMP"),0); if (i==-1) i=fileName.Find(_T(".bmp"),0); if (i!=-1) { //Creating thumbnail image for the file HBITMAP bitm=LoadPicture(filePath2); if (bitm!=NULL) {
CBitmap* pImage = NULL; pImage = new CBitmap(); pImage->Attach(bitm); int imgP=m_ImageList.Add(pImage,RGB(0,0,0)); //Link to the added listview item m_List.InsertItem(cn,fileName,imgP); } } // 加载icon 图片 i=fileName.Find(_T(".ico"),0); if (i==-1) i=fileName.Find(_T(".ICO"),0); if (i==-1) i=fileName.Find(_T(".rc"),0); if (i==-1) i=fileName.Find(_T(".rc2"),0); if (i!=-1) { ::SHGetFileInfo(filePath2,0,&finfo,sizeof(SHFILEINFO),SHGFI_ICON); m_ImageList.Add(finfo.hIcon);// 加入图标 m_List.InsertItem(cn,fileName,cn); } cn++; }while(::FindNextFile(hFind,&fd)); FindClose(hFind); m_List.SetRedraw(true); Invalidate(); UpdateWindow(); }
HBITMAP ListImage::LoadPicture(CString mFile) { CString pFSize; WCHAR wpath[MAX_PATH]; // MultiByteToWideChar(CP_ACP, 0,lpszBuf, -1, wpath, MAX_PATH); IPicture* pPic; OleLoadPicturePath(T2OLE((LPTSTR)(LPCTSTR)mFile), NULL, NULL, NULL, IID_IPicture,(LPVOID*)&pPic);
if (pPic==NULL) return NULL; HBITMAP hPic = NULL; pPic->get_Handle((UINT*)&hPic);
long nWidth=THUMWIDTH; long nHeight=THUMHEIGHT;
long mWid,mHei; pPic->get_Height(&mHei); pPic->get_Width(&mWid);
HBITMAP hPicRet = (HBITMAP)CopyImage(hPic, IMAGE_BITMAP, nWidth, nHeight , LR_COPYDELETEORG);
// Create Brushes for Border and BackGround HBRUSH hBrushBorder=::CreateSolidBrush(RGB(192, 192, 192)); HBRUSH hBrushBk=::CreateSolidBrush(RGB(255, 255, 255));
// Border Size RECT rcBorder; rcBorder.left=rcBorder.top=0; rcBorder.right=THUMWIDTH; rcBorder.bottom=THUMHEIGHT;
const float fRatio=(float)THUMHEIGHT/THUMWIDTH;
int XDest, YDest, nDestWidth, nDestHeight; // Calculate Rect to fit to canvas const float fImgRatio=(float)mHei/mWid; if(fImgRatio > fRatio) { nDestWidth=(THUMHEIGHT/fImgRatio); XDest=(THUMWIDTH-nDestWidth)/2; YDest=0; nDestHeight=THUMHEIGHT; } else { XDest=0; nDestWidth=THUMWIDTH; nDestHeight=(THUMWIDTH*fImgRatio); YDest=(THUMHEIGHT-nDestHeight)/2; }
CClientDC cdc(this); HDC hDC=::CreateCompatibleDC(cdc.m_hDC); HBITMAP bm = CreateCompatibleBitmap(cdc.m_hDC, THUMWIDTH, THUMHEIGHT); HBITMAP pOldBitmapImage = (HBITMAP)SelectObject(hDC,bm); // Draw Background ::FillRect(hDC, &rcBorder, hBrushBk);
// Draw Border ::FrameRect(hDC, &rcBorder, hBrushBorder);
HBITMAP hBmReturn= (HBITMAP)::SelectObject(hDC, pOldBitmapImage);
CDC hdcSrc, hdcDst;
hdcSrc.CreateCompatibleDC(NULL); hdcDst.CreateCompatibleDC(NULL);
// Load the bitmaps into memory DC CBitmap* hbmSrcT = (CBitmap*) hdcSrc.SelectObject(hPicRet); CBitmap* hbmDstT = (CBitmap*) hdcDst.SelectObject(hBmReturn);
// This call sets up the mask bitmap. hdcDst.BitBlt(XDest,YDest,nDestWidth, nDestHeight, &hdcSrc,0,0,SRCCOPY); //hdcDst.StretchBlt(XDest,YDest,nDestWidth, nDestHeight, &hdcSrc,0,0,48,48,SRCCOPY);
pOldBitmapImage = (HBITMAP)SelectObject(hdcDst.m_hDC,bm);
// Release used DC and Object DeleteDC(hDC); DeleteObject(hBrushBorder); DeleteObject(hBrushBk);
return pOldBitmapImage;
}
void ListImage::OnBnClickedOk() { // TODO: Add your control notification handler code here OnOK(); } ----------------------------------------------------------------------------------------------------
ListImage.h 代码如下
#pragma once #include "afxcmn.h" #include "afxwin.h"
// ListImage dialog
class ListImage : public CDialog { DECLARE_DYNAMIC(ListImage)
public: ListImage(CWnd* pParent = NULL); // standard constructor virtual ~ListImage(); CImageList m_ImageList; HBITMAP ListImage::LoadPicture(CString mFile);
// Dialog Data enum { IDD = IDD_DIALOG1 };
protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support virtual BOOL OnInitDialog(); DECLARE_MESSAGE_MAP() public: afx_msg void OnBnClickedButton1(); CListCtrl m_List; CEdit m_edit2; afx_msg void OnBnClickedOk(); };
在 CXXXApp::InitInstance() 下 使用 ASSERT(AfxOleInit() != FALSE ); //Initialize COM libraries m_List.SetBkImage("c:/background2.bmp"); m_List.SetTextBkColor(CLR_NONE); // 设置背景透明
首先将你的 CListCtrl 风格设置为ICON 风格
CImageList m_ImageList;
CListCtrl m_list;
m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
m_list.SetIconSpacing(CSize(140, 130)); //set pictures spacing
//wide of picture is 120,height is 90
m_ImageList.Create(120,90,ILC_COLORDDB|ILC_COLOR32,1,1);
m_list.SetImageList(&m_ImageList,LVSIL_NORMAL); //CImageList associates CListCtrl
// 此处用 GDI+,
Bitmap bmp( 文件的相对或绝路径 ); // 传入图片路径
int sourceWidth = 120; // 获得图片宽度, 这个120 和创建的120 保持相同。
int sourceHeight = bmp.GetHeight(); // 获得图片宽度
if(sourceHeight>120) / / 和 m_ImageList.Create(120 … ) 有很大关系,如果小于设
// 定的宽度,图片将无法显示。
{
sourceHeight=120;
}
else
{
sourceHeight=bmp.GetHeight();
}
Bitmap* pThumbnail = (Bitmap*)bmp.GetThumbnailImage(sourceWidth , sourceHeight , NULL, NULL); // 设定缩略图的大小
HBITMAP hBmp;
pThumbnail->GetHBITMAP(Color(255,255,255),&hBmp);
CBitmap *pImage = CBitmap::FromHandle(hBmp); // 转换成 CBitmap 格式位图
_wsplitpath(*photo_iter ,drive,dir,fname,ext );
wcscpy_s(itemName,fname);
wcscat_s(itemName,ext);
int a=m_imageList.Add(pImage,RGB(255,255, 255));
m_pictureList.InsertItem(a,itemName,a); // itemName, 你自己设法得到图片片的名字。名字会显示在图片下面。
// 这里要注意,一定要用 InsertItem(a,itemName,a); 之前的 m_list 不需要在 insert(I,_T(””)); 更不需要 setItemText(item,subItem,Text), 这可能会导致插入相同的图片。
顺便说下 GDI 这个鬼东西,不懂原理,直接说应用。会用的高手见笑。 VS2008 自带了 gdi+ ,不需要下载。
1 .声明头文件,在 stdafx 中,或者能被你编译到其他地方都可以。
#include <gdiplus.h> //GDI+ 声明,可以 GDI/GDI+ 混合使用
#pragma comment(lib, "gdiplus.lib")
using namespace Gdiplus;
2 .初始化 GDI+,
CMyApp: public CWinApp
{
…………
ULONG_PTR m_gdiplusToken;
…………
};
BOOL CMyApp::InitInstance() // 在这个函数中添加
{
// 初始化 GID+
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup( &m_gdiplusToken,&gdiplusStartupInput,NULL );
}
int CMobilePCApp::ExitInstance() // 释放 GDI+ 调用,这个函数需要自己写。别忘了声明。
{
GdiplusShutdown( m_gdiplusToken );
return CWinApp::ExitInstance();
}
当时这样做了后,我的 GDI+ 还是不能用,添加图片时候 Bitmap bmp( 文件的相对或绝路径 ); bmp 这个东西无效,里面有个空指针的东西,可见 GDI+ 并没有初始化。后来先,初始化 GDI+ 这段代码没有执行到。好了,那就把初始化的代码放到可以执行到的地方。
在主对话框的 InitInstance() 中添加
// 初始化 GID+
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup( &m_gdiplusToken,&gdiplusStartupInput,NULL );
好了, GDI+ 可以使用了,可以添加缩略图了。截图一张。
每行图片的数量随窗口大小自动排列。按下面设置属性。
CListCtrl 属性 Alignment 设置为 top Auto Arrage 设置为 True.
如有疑问,请留言。
//ClimageList 无效的原因 1 , creare 的大小; 2 ,如果是被重写的类,在 drawItem 重新绘制,不能在关联 CImageList
.h CListCtrlCl m_dataStatisticsList; CImageList m_DataImageList;
.cpp m_DataImageList.Create(44,30,ILC_COLOR24,2,2); //bmp.Attach(tempBitmap); bmp.LoadBitmap(IDB_CONTACT); int a=m_DataImageList.Add(&bmp,RGB(255,255,255)); int b=m_DataImageList.GetImageCount();
m_dataStatisticsList.SetImageList(&m_DataImageList,LVSIL_SMALL); for(int i=0;i<5;i++) { m_dataStatisticsList.InsertItem(i,_T(""),0); //0 是 CImageList 的第一个图标。 }
分析:在 m_DataImageList.Add(&bmp,RGB(255,255,255)); 之后,得到的 CImageList 的元素数量 b 还为 0 ,原因可能在于 m_DataImageList.Create(44,30,ILC_COLOR24,2,2); 前两个参数图片的宽度和长度大于了图片本身,就会 add 失败。
在 add 成功后, b 将成为 1 。 但是 m_dataStatisticsList.InsertItem(i,_T(""),0); 还不见图片,插入的文字倒是没有问题。 这个原因在于 m_dataStatisticsList 是一个被重写的类 CListCtrlCl 的对象。在 CListCtrlCl 中的 drawItem 并 没有绘出图片。
CListCtrl 是 MFC 的控件,所以只支持 HBITMAP 图片,这是我们可以将 iplimage* 转化成 HBITMAP; // 变量声明部分; // /// /// CListCtrl m_list; CImageList* m_pImgList; /// 初始化,将 bitmap 关联到 listctrl // // m_pImgList=new CImageList; m_pImgList->Create (200,200,ILC_COLOR32,20,20);// 前两个参数是设置图象大小的 m_pImgList->SetBkColor(RGB(125,125,0)); m_list.SetImageList(m_pImgList,0);// 将设置的位图列表选入 ListView 中去 /// 打开对话框添加图片 // /// / char m_szFilter[] = "bmp files(*.bmp)|*.bmp|jpg files(*.jpg)|*.jpg|png files(*.png)|*.png|tiff files(*.tiff)|*.tiff|All files(*.*)|*.*||"; CFileDialog fd(TRUE,NULL,NULL,OFN_FILEMUSTEXIST|OFN_HIDEREADON LY|OFN_ALLOWMULTISELECT, m_szFilter); BOOL nResult = (fd.DoModal() == IDOK) ? TRUE : FALSE; if (!nResult) // 点击 cancel { return; } // 把文件名称放到 CStringList 中 POSITION pos = fd.GetStartPosition(); while (pos) { CString currentFileName = fd.GetNextPathName(pos); //m_picNameList.AddTail(fileName); /* 显示位图文件 */ HBITMAP hBitmap; CBitmap pBitmap; m_list.InsertItem(m_picNum, currentFileName, m_picNum); IplImage* image, *pImgGray; image = cvLoadImage(currentFileName,1); //IplImage2Bitmap hBitmap = IplImage2Bitmap(image); pBitmap.Attach ( hBitmap ); m_pImgList->Add (&pBitmap, RGB(0,0,0)); DeleteObject(hBitmap); pImgGray = cvCreateImage(cvGetSize(image),image->depth,1); cvCvtColor(image,pImgGray,CV_RGB2GRAY); m_lImgsList.push_back(pImgGray); cvReleaseImage( ℑ ); // 增加图片数量 m_picNum++; } // 删除 listctrl 中的图片 // /// // 获取被删除图片的位置 POSITION pos = m_list.GetFirstSelectedItemPosition(); if(pos == NULL) { // MessageBox(" 请选择一项在删除 !"," 提示 ",MB_ICONINFORMATION); return; } int currentIndex = m_list.GetNextSelectedItem(pos); m_list.DeleteItem(currentIndex); // 重画被删图片以后的项目 //BOOL b = m_pImgList->Remove(currentIndex); m_list.RedrawItems(currentIndex, m_picNum); // 减少一张图片 m_picNum--; // 注: clistctrl 的 Auto Arrange 属性设为 ture ,这样,在删除图片的时候可以刷新(用后面的图像填充当前位置)