Click here to Skip to main content
15,884,628 members
Articles / Desktop Programming / MFC

Thumbnails Viewer using ListCtrl

Rate me:
Please Sign up or sign in to vote.
4.86/5 (73 votes)
27 Jan 2006CPOL1 min read 637K   19.1K   204   148
Show thumbnails of images, include JPG, TIFF, BMP, etc.

Sample Image - ThumbViewer.jpg

Introduction

There are several image libraries and sources currently available. So I made my mind up to make a free Image Viewer using a free image library, and I got many free demo programs. I think a good image viewer must be able to show thumbnail images in a selected directory. I found some sources showing thumbnails, but they didn't support several formats, only BMP files. This thumbnail viewer is based on CxImage, so if there is an image format supported by CxImage, this viewer also supports that format.

Implementation

I want to show you the core part in this article. How to make a CListCtrl, CImageList, and then how to load images and attach that image to an ImageList.

1. Creating CListCtrl and CImageList

I used a CListView instead of CListCtrl, but you know that CListView uses CListCtrl internally. So overriding Create(...) will make your icon view CListCtrl initially. And then on OnInitialUpdate(), make ImageList which can support 24 bit color images and attach to CListCtrl.

return CListView::Create(lpszClassName, _T("ListView"),
  dwStyle|LVS_SHOWSELALWAYS|LVS_ALIGNTOP|LVS_ICON|LVS_SINGLESEL|
  LVS_AUTOARRANGE, rect, pParentWnd, nID, pContext);

....
m_ImageListThumb.Create(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, ILC_COLOR24, 0, 1);
 ListCtrl.SetImageList(&m_ImageListThumb, LVSIL_NORMAL);

2. Load Images and Insert Items

Create a Compatible DC and a Bitmap Handle. Stretch a loaded image to the Bitmap Handle and then attach it to CBitmap. Finally, replace CBitmap with an image in the ImageList.

unsigned __stdcall CThumbViewerView::LoadThumbNail(LPVOID lpParam)
{
 CThumbViewerView* pView=(CThumbViewerView*)lpParam;
 CThumbViewerDoc* pDoc=pView->GetDocument();

 CListCtrl& ListCtrl=pView->GetListCtrl();
 CImageList* pImgList=&pView->m_ImageListThumb;

 // reset our image list
 for(int i=0; i<pImgList->GetImageCount(); i++)
  pImgList->Remove(i); 

 // remove all items from list view
 ListCtrl.DeleteAllItems();

 pImgList->SetImageCount(pDoc->m_vFileName.size());

 char path[MAX_PATH];
 vector<CString>::iterator iter;
 
 // Set redraw to FALSE to avoid flickering during adding new items
 ListCtrl.SetRedraw(FALSE);
 int nIndex=0;
 for(iter=pDoc->m_vFileName.begin(); 
     iter!=pDoc->m_vFileName.end() && pView->m_bTerminate!=true; 
     iter++, nIndex++)
 {
          ListCtrl.InsertItem(nIndex, *iter, nIndex);
 }

 ListCtrl.SetRedraw(TRUE);
 ListCtrl.Invalidate();

 // 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=THUMBNAIL_WIDTH;
 rcBorder.bottom=THUMBNAIL_HEIGHT;

 const float fRatio=(float)THUMBNAIL_HEIGHT/THUMBNAIL_WIDTH;

 int XDest, YDest, nDestWidth, nDestHeight;
 nIndex=0;
 for(iter=pDoc->m_vFileName.begin(); 
     iter!=pDoc->m_vFileName.end() && pView->m_bTerminate!=true; 
     iter++, nIndex++)
 {
  // Load Image File
  sprintf(path, "%s\\%s", pDoc->m_strCurrentDirectory, *iter);

  int nImageType=pDoc->GetTypeFromFileName(path);
  if(nImageType==CXIMAGE_FORMAT_UNKNOWN)
   continue;

  CxImage image(path, nImageType);

  if(image.IsValid()==false)
   continue;

  // Calculate Rect to fit to canvas
  const float fImgRatio=(float)image.GetHeight()/image.GetWidth();
  if(fImgRatio > fRatio)
  {
   nDestWidth=THUMBNAIL_HEIGHT/fImgRatio;
   XDest=(THUMBNAIL_WIDTH-nDestWidth)/2;
   YDest=0;
   nDestHeight=THUMBNAIL_HEIGHT;
  }
  else
  {
   XDest=0;
   nDestWidth=THUMBNAIL_WIDTH;
   nDestHeight=THUMBNAIL_WIDTH*fImgRatio;
   YDest=(THUMBNAIL_HEIGHT-nDestHeight)/2;
  }

  CClientDC cdc(pView);
  HDC hDC=::CreateCompatibleDC(cdc.m_hDC);
  HBITMAP bm = CreateCompatibleBitmap(cdc.m_hDC, THUMBNAIL_WIDTH, 
                                      THUMBNAIL_HEIGHT);
  HBITMAP pOldBitmapImage = (HBITMAP)SelectObject(hDC,bm);
  // Draw Background
  ::FillRect(hDC, &rcBorder, hBrushBk);

  // Draw Image
  image.Stretch(hDC, XDest, YDest, nDestWidth, nDestHeight);

  // Draw Border
  ::FrameRect(hDC, &rcBorder, hBrushBorder);

  SelectObject(hDC, pOldBitmapImage);

  // Attach to Bitmap and Replace image in CImageList
  CBitmap bitmap;
  bitmap.Attach(bm);
  pImgList->Replace(nIndex, &bitmap, NULL);

  // Redraw only a current item for removing flickering and fast speed.
  ListCtrl.RedrawItems(nIndex, nIndex);

  // Release used DC and Object
  DeleteDC(hDC);
  DeleteObject(bm);
 }
 DeleteObject(hBrushBorder);
 DeleteObject(hBrushBk);

 ListCtrl.Invalidate();
 pView->m_bRunning=false;
 pView->m_bTerminate=false;

 _endthreadex( 0 );

 return 0;
}

Acknowledgment

You can download CxImage freely from here.

History

  • Ver. 1.0  15, Sep. 2003
    • First release.
  • Ver. 1.1  24, Mar. 2005
    • Fixed crashing when changing a directory fast.
    • Supports Unicode option using preprocessor _UNICODE.

License

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


Written By
Web Developer
Korea (Republic of) Korea (Republic of)
Youngjin Kim lives in South Korea. I'm interested in every part of Computer Science, cause it has not been long time since graduate a University.
But now I'm working and researching on Pattern Recognition. Using that trying to recognize a Handwriting Prints. Korean and Chinese are my interesting Research Part.

Comments and Discussions

 
AnswerRe: How do I do this in VB? Pin
moah1-Jul-04 13:35
moah1-Jul-04 13:35 
GeneralRe: How do I do this in VB? Pin
Brad Fackrell6-Jul-04 2:31
Brad Fackrell6-Jul-04 2:31 
Questionhow can i show a jpg file on a static box?thanks Pin
yangchunyuycy28-Apr-04 16:10
yangchunyuycy28-Apr-04 16:10 
AnswerRe: how can i show a jpg file on a static box?thanks Pin
moah29-Apr-04 18:52
moah29-Apr-04 18:52 
GeneralRe: how can i show a jpg file on a static box?thanks Pin
yangchunyuycy29-Apr-04 21:03
yangchunyuycy29-Apr-04 21:03 
GeneralRe: how can i show a jpg file on a static box?thanks Pin
Anonymous30-Apr-04 4:06
Anonymous30-Apr-04 4:06 
GeneralRe: how can i show a jpg file on a static box?thanks Pin
moah2-May-04 13:30
moah2-May-04 13:30 
Generala question about Thumbnails Viewer using ListCtrl Pin
yuyi20035-Mar-04 1:52
yuyi20035-Mar-04 1:52 
GeneralRe: a question about Thumbnails Viewer using ListCtrl Pin
hello111110-Mar-04 21:11
hello111110-Mar-04 21:11 
GeneralRe: a question about Thumbnails Viewer using ListCtrl Pin
yuyi200312-Mar-04 1:33
yuyi200312-Mar-04 1:33 
GeneralRe: a question about Thumbnails Viewer using ListCtrl Pin
moah28-Mar-04 21:53
moah28-Mar-04 21:53 
Generalin .NET 7.1 It has two compile error. Pin
Junee Lee18-Feb-04 19:59
Junee Lee18-Feb-04 19:59 
GeneralRe: in .NET 7.1 It has two compile error. Pin
moah4-Mar-04 13:37
moah4-Mar-04 13:37 
QuestionWhether CXImage Works on eVC 4.0?? Pin
P. Gnana Prakash12-Feb-04 21:35
P. Gnana Prakash12-Feb-04 21:35 
AnswerRe: Whether CXImage Works on eVC 4.0?? Pin
moah4-Mar-04 13:20
moah4-Mar-04 13:20 
GeneralHi its a gr8 job, i need your help Pin
Sameer2414-Jan-04 19:25
Sameer2414-Jan-04 19:25 
GeneralRe: Hi its a gr8 job, i need your help Pin
moah26-Jan-04 17:37
moah26-Jan-04 17:37 
QuestionConvert this to ActiveX?? Pin
jistabout15-Nov-03 12:10
jistabout15-Nov-03 12:10 
AnswerRe: Convert this to ActiveX?? Pin
moah26-Jan-04 17:31
moah26-Jan-04 17:31 
GeneralRe: Convert this to ActiveX?? Pin
jistabout23-Apr-04 11:54
jistabout23-Apr-04 11:54 
GeneralRe: Convert this to ActiveX?? Pin
moah25-Apr-04 22:24
moah25-Apr-04 22:24 
GeneralRe: Convert this to ActiveX?? Pin
defcon221-Oct-04 2:26
defcon221-Oct-04 2:26 
GeneralRe: Convert this to ActiveX?? Pin
moah21-Oct-04 14:30
moah21-Oct-04 14:30 
GeneralSome Problems about thread Pin
moah22-Sep-03 20:00
moah22-Sep-03 20:00 
GeneralRe: Some Problems about thread Pin
bvp11-Oct-04 9:08
bvp11-Oct-04 9:08 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.