Thumbnails Viewer using ListCtrl
Show thumbnails of images, include JPG, TIFF, BMP, etc.
- Download source files - 924 Kb
- Download Unicode project files - 5.74 Kb
- Download demo project - 389 Kb
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
.