Click here to Skip to main content
Click here to Skip to main content

Showing the Image file thumbnail view in ListView control using VC++ 6.0

By , 1 Oct 2004
 

Sample Image - Simple_Thumbnail_Listview.jpg

Introduction

CListImageCtrl is MFC control derived from the CListCtrl class. The control has an extended feature for loading thumbnail view to the List control. It has a drag and drop functionality to get the image files from the window explorer and draw the thumbnail view for that image file. Here I have simply added a function for drawing that thing.

Step by Step procedure for creating the thumbnail

To develop the thumbnail ListView control, see the below section for step by step operations.

Create the ListImage Project

  1. Create a New Project using the VC++ - MFC AppWizard (.exe).
  2. Select the Dialog based option in the wizard - Step 1.
  3. Finish the wizard.

Now the new project classes added to the workspace (You can see the class files from the fileView tab in Project Workspace tree.

Create the ListImage class for the thumbnail image

  1. Go to the ClassView tab, select the project name and add a new MFC class by clicking the right mouse button on it.
  2. Select CListCtrl as a base class for that.
  3. Now the new class will be created in the project workspace.

How to bind the class to the listcontrol?

  1. Select the Dialog form from the ResourceView.
  2. Click the right mouse button from the form dialog and select the ClassWizard from the popup menu.
  3. Now go to Member variable section select ListControl from the control list.
  4. Press the Add variable button to add a variable for the ListControl. Select the variable type as the new created class name(ClistImageCtrl or ur added class name) in the Add member variable form.

Enable the Drop file for List Control…

  1. Select the Dialog form from the ResourceView.
  2. Open the Property window for List Control.
  3. In that check the “Accept Files” check box from the Extended Styles.

Get the dropped files from the Explorer

  1. Select the ListImage class from the classview.
  2. Open the class wizard for that.
  3. Add WM_DROPFILES Message function.
  4. OnDropFiles() function will be automatically added to the class.
void CListImageCtrl::OnDropFiles(HDROP hDropInfo) 
{
    WORD wNumFilesDropped = DragQueryFile(hDropInfo, -1, NULL, 0);

    CString firstFile="";
    CFile Cf;
    DWORD TmpVal;
    char szText[MAX_PATH];
    int kk=0;
    int tTot=(int)wNumFilesDropped;
    int m_TotCount;

    for (WORD x = 0 ; x < wNumFilesDropped; x++) 
    {
        kk++;
        // Get the number of bytes required by the file's full pathname
        WORD wPathnameSize = DragQueryFile(hDropInfo, x, NULL, 0);

        // Allocate memory to contain full pathname & zero byte
        char * npszFile = (char *) LocalAlloc(LPTR, wPathnameSize += 1);

        // If not enough memory, skip this one
        if (npszFile == NULL) continue;
        DragQueryFile(hDropInfo, x, npszFile, wPathnameSize);

        if (firstFile=="")
            firstFile=npszFile;

        CString nFileText;
        CString nPath;
        CString pItemText=npszFile;
        CFile Cf;

        int i=pItemText.ReverseFind('\\');

        nFileText=pItemText.Mid(i+1);
        nPath=pItemText.Left(i+1);
        i=nFileText.Find("%");
        if (i==-1)
        {
            i=pItemText.Find(_T(".jpg"),0);
            if (i==-1)
                i=pItemText.Find(_T(".jpeg"),0);
            if (i==-1)
                i=pItemText.Find(_T(".JPG"),0);
            if (i==-1)
                i=pItemText.Find(_T(".JPEG"),0);

            if (i!=-1)
            {
                m_TotCount=GetItemCount();
                InsertItem(m_TotCount,nFileText,0);
                SetItemText(m_TotCount, 1, nPath);
                //Get File size
                DoEvents();
                if (Cf.Open(pItemText,0,0)==TRUE)
                {
                    TmpVal = Cf.GetLength();
                    wsprintf(szText, "%lu", TmpVal);
                    if (TmpVal>1024)
                    {
                        double kTmpVal=TmpVal;
                        double kdvTmp=kTmpVal/1024;
                        TmpVal=TmpVal/1024;
                        if (TmpVal>1024)
                        {
                            double dTmpVal=TmpVal;
                            double dvTmp=dTmpVal/1024;
                            CString szT= 
                              ConvertDoubleToString(dvTmp) + _T(" MB"); 
                            wsprintf(szText, "%s", szT);
                        }
                        else
                        {
                            CString kszT= 
                              ConvertDoubleToString(kdvTmp) + _T(" KB"); 
                            wsprintf(szText, "%s", kszT);
                        }
                    }
                    else
                        wsprintf(szText, "%lu BYTES", TmpVal);
 
                    SetItemText(m_TotCount, 2, szText);
                }
                Cf.Close();
                HBITMAP bitm=LoadPicture(pItemText);
                if (bitm!=NULL)
                {
                    CBitmap*    pImage = NULL;    
                    pImage = new CBitmap();                    
                    pImage->Attach(bitm);
                    int imgP=m_imageList.Add(pImage,RGB(0,0,0));
                    SetItem(m_TotCount, 0, LVIF_IMAGE, NULL, imgP,0, 0, 0);
                }
            }
        }

        // clean up
        LocalFree(npszFile);
    }

    // Free the memory block containing the dropped-file information
    DragFinish(hDropInfo);

    // if this was a shortcut, we need to expand it to the target path
    int result=GetItemCount();
    SetItemState(result, LVIS_SELECTED | 
        LVIS_FOCUSED | LVIS_ACTIVATING, 
        LVIS_SELECTED | LVIS_FOCUSED | LVIS_ACTIVATING); 
    //m_ProgList.SetActiveItem(k);
    //m_ProgList.SetFocus();
    result--;
    EnsureVisible(result, TRUE);
    SetFocus();
    SetRedraw(TRUE);
    RedrawWindow(NULL,NULL);

    CListCtrl::OnDropFiles(hDropInfo);
}

Creating Thumbnail image for the Picture file

  1. Add the LoadPicture function to the ListImage class.
HBITMAP CListImageCtrl::LoadPicture(CString mFile)
{
    CString pFSize;
    WCHAR wpath[MAX_PATH];
    MultiByteToWideChar(CP_ACP, 0, mFile, -1, wpath, MAX_PATH);
    IPicture* pPic;
    OleLoadPicturePath(wpath, 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;
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Karpaga Rajan
Web Developer
India India
Member
Around 7 years of experience in software development, system design, prototyping, testing, implementation, maintenance and documentation.
 
Experience in System oriented programming (developed Anti – Virus Kit, Network security system, etc) and Embedded systems.
 
Capable of developing Device Drivers and building Custom ActiveX Controls in VC++ 6.0
 


Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 3groupfly_vdream15 Aug '10 - 23:56 
I'm sorry to tell you that you maybe upload wrong program, or the wrong picture to the src
Generalplease help mememberwangshumin27 Sep '09 - 3:26 
fatal error RC1015: cannot open include file 'res\ListImage.rc2'
 
please help.

 
Email:wsmcnu@gmail.com
Generalmemory leak and memory overflow found in this projectmemberliu8han10 Sep '09 - 19:22 
If you load enough quantities pictures in this application. you will find it does work at all. In my test, the limitation is 4973 (720 * 480 pixel) images.
 
After that I nvestigated in this code and found solution eventually.
 
Code snapshot
in ListImageCtrl.cpp
at line
 
95 //Adding Bitmap to the Imagelist
96 CBitmap* pImage = NULL;
97 pImage = new CBitmap();
98 pImage.Attach(bitm);
99 int imgP=m_imageList.Add(pImage,RGB(0,0,0));
100 //Link to the added listview item
101 InsertItem(m_TotCount,nFileText,imgP);
 
add code below
 
pImage.Detach();
DeleteObject( bitm );
delete pImage;
GeneralBeginner code and wrong methodmemberkilt11 Aug '09 - 6:15 
Horrible and beginner code.
The right method is to use COM (Thumbnail interfaces), which is what Explorer uses.
GeneralRe: Beginner code and wrong methodmemberhugh4vc14 Aug '09 - 3:02 
so please tell us the right way. thank u!
GeneralThe blue mask when image focusedmemberMember 373290315 Jul '09 - 17:32 
Any body know how to do this.
 
Please help
 
~Regards
GeneralThank you!memberxluo13 Mar '08 - 16:11 
It is useful to me,Thank you very much!
GeneralImprovementmemberStruk Igor18 May '07 - 2:05 
Images are streched in ListCtrl, to fix it we have to calculate Ratio before calling CopyImage (and pass correct Ratio-parameter to it).
 
OleLoadPicturePath allow to load not only JPG files, but BMP (bitmap), WMF (metafile), ICO (icon) and GIF format.
 
c++ developer. Kiev, Ukraine

GeneralCompiter Error-pls helpmemberzhaque18 Feb '07 - 0:25 
got compiler error:
fatal error RC1015: cannot open include file 'res\ListImage.rc2'
 
please help
Cry | :(( Sigh | :sigh:
GeneralRe: Compiter Error-pls helpmemberzhaque18 Feb '07 - 1:24 
New programmer, I followed by still got errors: Can some one send me
compiled code.
Thanks,
 

\vc\ListImage\listImageCtrl.cpp(90) : error C2065: 'DoEvents' : undeclared identifier
D:\vc\ListImage\listImageCtrl.cpp(105) : error C2065: 'ConvertDoubleToString' : undeclared identifier
D:\vc\ListImage\listImageCtrl.cpp(121) : error C2065: 'LoadPicture' : undeclared identifier
D:\vc\ListImage\listImageCtrl.cpp(121) : error C2440: 'initializing' : cannot convert from 'int' to 'struct HBITMAP__ *'
Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
D:\vc\ListImage\listImageCtrl.cpp(127) : error C2065: 'm_imageList' : undeclared identifier
D:\vc\ListImage\listImageCtrl.cpp(127) : error C2228: left of '.Add' must have class/struct/union type
QuestionRetrieving Images from a CImageListmembergeoyar15 Feb '07 - 9:23 
Ths is a very good and usegul article. Thank you.
 
I have a question:
To draw the selected image you download the image from its file again:
Image img( A2W(strPath) );
...........................
 
Is it possible to retrieve the image from the CListCtrl, like
CListCtrl m_listCtrl;
LVITEM lwi;
................// prepare lwi
m_listCtrl.GetItem(&lvi);
CImageList* pImageList = m_listCtrl.GetImageList();

IMAGEINFO ii;
....................// prepare ii
pImageList->GetImageInfo(lvi.iImage, &ii);
CImage image;
image.Attach(ii.hbmpImage);
...................// Draw it
 
I tried it, but it failed: on bitmap 20x20 entered in CImage list it retrieved the empty bitmap 20x280.
Maybe you know what is wrong?

 
geoyar

GeneralSuggestion if I may...memberPandele Florin31 Jul '06 - 5:19 
I would strongly suggest that you modify this to use CXImage for decoding/drawing.It is a lot more esier to use and can open a lot of formats.CxImage is a project here, on CodeProject.
Generaladd checkboxmemberrung xanh26 Jul '06 - 23:08 
i want to add a checkbox into each thumbnail. how can i do that? thanks
 
neverchange

QuestionHow remove thr file namememberalwittta28 Apr '06 - 20:57 
Hi,
I would like to know is it possible to remove the file name of the thumbnail image, from the list control. If so, please explaine?
 
Thnaks and regards
Alvin
 


 
This is alwittta
AnswerRe: How remove thr file namememberKarpaga Rajan28 Apr '06 - 21:14 
Hi,
 
In the List Control you cannot add thumbnail without text (filename). What you can do is you can add blank space ("") in "SetItemText()" function instead of displaying filename. But when you select the thumbnail in the run mode, a blank selection will be appeared in the bottom of the thumbnail.
 

..............
thank
Karpaga Raj
GeneralSample downloaded is different than the snap given !!memberji mehta7 Apr '06 - 1:46 
Hi,
 
I have downloaded the file that you put the link for at the top. But after compiling it first thing is RES folder is missing. And another thing is, it does not give the same output as you shown in the snap in your article.. it shows me report style view of list control. How can I get exactly same kind of output ? And is it possible to change the resolution of preview on the fly ?
 
Regards,
Jigar Mehta
 

QuestionDoes it support larger or smaller image preview size ?memberji mehta7 Apr '06 - 1:24 
Hi,
 
I want to change the image thumbnail preview size on the runtime. So, does this class support that ?
 
Regards,
Jigar mehta
Generalconversion from CString to char* requiredsusshutkey22 Jul '05 - 0:38 
i ran the program at first, it worked very well. i sould see the thumbnails as said.
 
when a copies the function LoadPicture to myProgram.cpp i got the following error on compilation.
 
error C2664: 'MultiByteToWideChar' : cannot convert parameter 3 from 'class CString' to 'const char *'
 
after many attempts i am unable to find a way to give proper path of the file or make conversion from CString to char* work.
 
please help.
thnx in adv.
GeneralRe: conversion from CString to char* requiredsussAli Ghanbari16 Aug '05 - 19:52 
You can use:
      char *str;
     
      str = new char[100];
      if(!str)
         exit(1);
      strcpy(str, TheCStringVariable); /*convert CString to char **/
     
You can e-mail me: MicroDeniz@Gmail.com
You will make me happySmile | :)
GeneralRe: conversion from CString to char* requiredsussGoosiCodeName-Ali17 Aug '05 - 1:58 
You can use:
      CString b = "Hello!";
      char *a;

      a = new char[100];
      ASSERT(a);
      strcpy(a, b);
      //another way: wsprintf(a, "%s", b);
      MessageBox(a);Smile | :)
Good bye
Email me;)
GeneralCan't do it on another Image classmemberMaverick7 Jan '05 - 7:31 
First of all, thanks a lot for this code.. this really helped me a lot.. this is a nice codeSmile | :)
 
but i need to modify this so that i can use a Image Class from another library instead of IPicture...
 
i replace this code:
CBitmap* hbmSrcT = (CBitmap*)
//hPicRet got from IPicture handles...
hdcSrc.SelectObject(hPicRet);

 
with:

hdcSrc.CreateCompatibleDC(NULL);
//from a third party library
//Draw function draws(image on supplied HDC)
image->Draw(hdcSrc.GetSafeHdc());

 
I just replaced those codes and removed the codes that relates to IPicture..
 
Is that enough? because is still don't get to display the images in ListCtrl..
 
Thanks in advance.. for you help Smile | :)
 
Anton
 
"the possibilities are endless....
GeneralRotating an ImagememberAlex Evans4 Jan '05 - 9:28 
Any idea, how can I ROTATE 90, 180 etc using an IPicture object, once it is loaded and showing on screen...
 
Thanks
Alex

QuestionHow do I add another list to display images in another folder?memberjoshuafoo19801 Dec '04 - 21:29 
Hi,
 
I am trying to have two sets of list displaying pictures from different folders, any help about this? Will be much appreciated!
 
Thank you!
Joshua
AnswerRe: How do I add another list to display images in another folder?memberKarpaga Rajan1 Dec '04 - 23:25 
hi,
If you want to display the folders images in listview,
first get the file in that folder by FindFileFirst() functions and you can pass the filename in the image load function(which will load the thumb images to the listview).
 
If you need any coding assistance...you can mail me.(talk2karpagarajan@hotmail.com)
bye
RajanRose | [Rose]
GeneralNeeds serious code clean-up.memberPeter Ritchie13 Nov '04 - 7:19 
One of the things that people look for a CodeProject is quality source code.
 
Your program was obviously the result of much research. You fiddled the code till it worked; and it's not clear to you why. You've got a blend of SDK and MFC code that is inconsistent and hard to follow.
 
Why are you copying the bitmap you loaded? What's wrong with the HBITMAP returned from IPicturc::get_Handle()?
 
It would be nice if all that work with aspect ratios actually resulted in a thumbnail with the aspect ratio was preserved.
 
Why are CreateCompatibleBitmap and CreateCompatibleDC called so many times? You only need two DC objects and two bitmap objects.
 
You also only need three SelectObject calls, not five.
 

GeneralRe: Needs serious code clean-up.memberNic Wilson2 Apr '09 - 22:20 
Easy to criticize isn't it. If you know so much why don't you fix it. Either put up or shut up
GeneralThe blue mask when image focusedmemberkwlee888 Nov '04 - 16:34 
I saw that the sample code if thumb view always use LVS_ICON style, and get the problem when image focused, it's blue masked and not easy to see the image.
 
I also checked that MS file manager's view-> thumbview just display a blue frame which will not affect original image. do u know how to do that?
 

Best Regards,
KW
GeneralDrag and Drop image item in CListViewmemberphieu1 Nov '04 - 21:27 
Could you tell the way to implement drag and drop image item in thumbnailview in CListCtrl? It likes thumbnail view in explorer!
D'Oh! | :doh:
Thank you!

GeneralRe: Drag and Drop image item in CListViewmemberKarpaga Rajan1 Nov '04 - 21:36 
Hi,
If you want to enable the drag and drop in a CListCtrl, first enable the "Accept File" Property of your control(List view). And enable the WM_DROPFILES message mapping. In that function insert the coding which i have given in this article.
Go through the source code. You can find the OnDropFiles event.
If you need the full source code, click on the below link
Click my link - www.buddiesinfotech.com/ListImage.zip
 
bye thanks
Rose | [Rose]
Rajan

GeneralRe: Drag and Drop image item in CListViewmemberphieu3 Nov '04 - 14:06 
Hi Rajan,
 
Thank you, but You are misunderstanding me!Smile | :)
I mention to drag-drop within itself - CListCtrl.
Your code only solved drop files, ok?
 
Simply, it is the same Explorer when you open an image folder (My Picture,....) and you see image in thumbnail view mode, you drag and drop these thumbnail images.
You have other ideas?D'Oh! | :doh:
 
Thanks and regards!
PhucFBK
phucfbk@yahoo.com
GeneralRe: Drag and Drop image item in CListViewsussAnonymous3 Nov '04 - 18:24 
Hi PhucFBK
Yeah...thats ok.
 
To drag and drop within the CListCtrl,
You have to Add the MESSAGE HANDLER "LVN_BEGINDRAG" for the CListCtrl. And add the Windows messaging function called ON_WM_QUERYDRAGICON(WM_QUERYDRAGICON),WM_LBUTTONUP.
In that you have to do the coding for drag and drop within that control. If you need any source code for that please contact to my email id talk2karpagarajan@yahoo.com
 
bye
thanks
Rajan
GeneralRe: Drag and Drop image item in CListViewmemberphieu3 Nov '04 - 19:03 
Hi Rajan,
 
You are very kind!
I am happy to see your code about the problem, I will get alot of things in it!
 
If possible, pls send to me: phucfbk@yahoo.com, or phucfbk@gmail.com
 
Thanks you!
 

QuestionCould you explain?memberWREY1 Oct '04 - 23:36 
I have a file with ".jpg" pictures, how do I get that to become, "res\ListImage.rc2" which is where the compile is failing because it cannot open, "res\ListImage.rc2"?
 
Thanks!
 
Unsure | :~
 
William
 
Fortes in fide et opere!
AnswerHi WilliamsussAnonymous2 Oct '04 - 0:21 
Hi...
Its my sample one.
You can do your own code using my article.
If you want the full source code,get it from the following link
 
www.discussweb.com
in that goto
"Discussweb Web Design Forum > Application Programming > Visual C++ and C Style languages" topic "Showing the Image file thumbnail view in ListView control using VC++ 6.0"
Or
 
Click my link - www.buddiesinfotech.com/ListImage.zip
bye thanks
Rose | [Rose]
Rajan
GeneralVery Usefulmemberklassics1 Oct '04 - 6:01 
Very useful and informative post... thnks Karpagaraj..
 

KlassiCs
http://www.discussweb.com
GeneralGood topic and program but...memberJeremy Davis1 Oct '04 - 4:57 
You could improve the formatting of the article a bit.
 
Rose | [Rose]
 


I feel like I'm diagonally parked in a parallel universe
 
Jerry Davis
http://www.astad.org
http://www.jvf.co.uk
GeneralRe: Good topic and program but...memberJeremy Davis4 Oct '04 - 22:27 
It's looking much better now! Cool | :cool:
 


I feel like I'm diagonally parked in a parallel universe
 
Jerry Davis
http://www.astad.org
http://www.jvf.co.uk

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 1 Oct 2004
Article Copyright 2004 by Karpaga Rajan
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid