加入图片

    技术2022-11-28  49

    步骤简要如下:

    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 ,这样,在删除图片的时候可以刷新(用后面的图像填充当前位置)

    最新回复(0)