Click here to Skip to main content
14,299,664 members

List Control displaying image thumbnails

Rate this:
3.43 (37 votes)
Please Sign up or sign in to vote.
3.43 (37 votes)
4 Jan 2000
Demonstrates using a list control to display thumbnail views of images

Sample Image - thumbnailview.jpg


In an image viewer application it may be useful to display a list of image thumbnails. Also, one may need to display a list of images into a list control or a list view. Displaying the images in a list control inside a dialog box or a CFormView-derived class may be somehow easier to implement, since a CListCtrl-derived object can be used, but displaying it in a CListCtrl-derived class is not so obvious, because we cannot use our own CListCtrl-derived class into a CListView.


The solution presented in this article uses a JPEG reader class to read JPEG images and display them into a CListCtrl. The idea is to create an image list that holds the icons created from the JPEG thumbails.

The first problem arises with the fact that MFC class CImageList does not support higher color depths than 16 colors (4 bits per pixel). Another interesting issue is that image loading takes quite some time. This article addresses both these issues.

1. Creating an image list with higher color depth.

The less-known SDK macro ImageList_Create meets this problem.

// Create the image list with 100*100 icons and 32 bpp color depth
HIMAGELIST hImageList=ImageList_Create(100, 100, ILC_COLOR32, 0, 10);

// load the starting bitmap ("Loading..." and "Corrupt file")
CBitmap dummy;
m_imageList.Add(&dummy, RGB(0, 0, 0));

// Use the image list in the list view
GetListCtrl().SetImageList(&m_imageList, LVSIL_NORMAL);
GetListCtrl().SetImageList(&m_imageList, LVSIL_SMALL);

2. Adding items to the list control

Adding items to the list control is quite simple if we are not writing a time-critical application. If there is a great number of thumbnails to load, the user will see just a moving scroll bar flashing on the screen while the images are being loaded from disk. Instead we can use a simple thread mechanism to add the list items while another thread just loads the images, and all this while the user continues to interact with the application.

The member function that loads items into the list control will be something like:

// structure used to pass parameters to a image adder thread
struct threadParamImage
	CString		folder;   // the folder to be scanned for thumbnails
	CThumbnailView*	pView;    // the view that accomodates them
	HANDLE		readPipe; // the pipe used to pass thumbnail filenames to the 
	                          // JPEG loader thread

// structure used to pass parameters to a JPEG image loader thread
struct threadParam
	CThumbnailView*	pView;    // the view that shows thumbnails
	HANDLE		readPipe; // the pipe used to pass thumbnail filenames to the
	                          // JPEG loader thread

HANDLE	hThread           = NULL; // handle to the JPEG image loader thread
HANDLE	readPipe          = NULL; // read and write ends of the communication pipe
HANDLE	writePipe         = NULL;
HANDLE skipImages         = NULL; // handle to the semaphore that signals the pipe 
                                  //does no longer hold consistent data
HANDLE imageFiller        = NULL; // handle to the thumbnail adder thread
HANDLE imageFillerSemaphore = NULL; // thread termination flag (when this semaphore 
                                    // goes signaled, the thread must exit)
HANDLE imageFillerCR      = NULL; // thumbnail adder thread critical section semaphore
HANDLE imageFillerWait    = NULL; // second thumbnail adder thread critical section semaphore

// Fill in list control with thumbails from a specified folder
BOOL CThumbnailView::FillInImages(CString folder)
	// create semaphores the first time only
	if (!imageFillerSemaphore)
		imageFillerSemaphore=CreateSemaphore(NULL, 0,1, NULL);
		imageFillerCR=CreateSemaphore(NULL, 1,1, NULL);
		imageFillerWait=CreateSemaphore(NULL, 1,1, NULL);

	// critical region starts here
	WaitForSingleObject(imageFillerCR, 0);

	// create thread parameters
	threadParamImage* pParam=new threadParamImage;

	// and the thread
	DWORD dummy;
	imageFiller=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ImageFillerThread,
                                 pParam, 0, &dummy);

	return TRUE;

While the image filler thread is:

// thumbnail adder thread
DWORD ImageFillerThread(DWORD param)
	// get thread parameters
	threadParamImage* pParam=(threadParamImage*)param;
	CString folder=pParam->folder;
	CThumbnailView* pView=pParam->pView;
	HANDLE readPipe=pParam->readPipe;
	// cleanup
	delete pParam;

	// wait for previous copies to stop
	WaitForSingleObject(imageFillerWait, INFINITE);

	// clear previous images from list control

	// start scanning designated folder for thumbnails
	HANDLE find;
	find=FindFirstFile(folder+"\\_thumbs\\*.*", &fd);

	// return if operation failed
		ReleaseSemaphore(imageFillerWait, 1, NULL);
		return 0;

	// critical section ends here
	ReleaseSemaphore(imageFillerCR, 1, NULL);

	// start adding items to the list control
		if (WaitForSingleObject(imageFillerSemaphore, 0)==WAIT_OBJECT_0)
			// thread is signaled to stop
			// signal skip to JPEG file loader
			int skip=-1;
			DWORD dummy;
			WriteFile(writePipe, &skip, sizeof(int), &dummy, NULL);
			ReleaseSemaphore(skipImages, 1, NULL);

		ok=FindNextFile(find, &fd);

		if (ok)
			int item=pView->GetListCtrl().InsertItem(pView->GetListCtrl().GetItemCount(), 
			                                         fd.cFileName, 0);
			pView->GetListCtrl().SetItemPosition(item, CPoint(105*item, 5));
			pView->AddImage(CString(folder+"\\_thumbs\\")+fd.cFileName, item);
	while (find&&ok);

	// done adding items
	ReleaseSemaphore(imageFillerWait, 1, NULL);

	return 0;

The last but not the least is the JPEG image loader thread:

// JPEG image loader thread
DWORD ImageLoaderThread(DWORD param)
	// wait to get a filename, then build the image, add it to the image list
	// then update list control
	CThumbnailView* pView=(CThumbnailView*)param;
	DWORD dummy;
	char buffer[1024];

		int itemIndex;
		int size;

		if (WaitForSingleObject(skipImages, 0)==WAIT_OBJECT_0)
			// skip to marker
				ReadFile(readPipe, &itemIndex, sizeof(int), &dummy,
				ReadFile(readPipe, &size, sizeof(int), &dummy, NULL);
				ReadFile(readPipe, buffer, size, &dummy, NULL);
			while (1);

		// get data from pipe
		ReadFile(readPipe, &itemIndex, sizeof(int), &dummy, NULL);
		ReadFile(readPipe, &size, sizeof(int), &dummy, NULL);
		ReadFile(readPipe, buffer, size, &dummy, NULL);

		// is the file name valid ?
		if(OpenFile(buffer, &ofs, OF_EXIST)==HFILE_ERROR)continue;

		// load an image from disk (using PaintLib)
		CWinBmp bitmap;
		CAnyPicDecoder decoder;
			decoder.MakeBmpFromFile(buffer, &bitmap, 0);
		catch (CTextException exc)
			pView->GetListCtrl().SetItem(itemIndex, 0, LVIF_IMAGE, NULL,
			                             1, 0, 0, 0);

		// create a CBitmap object from the data within the CWinBmp object
		BITMAPINFOHEADER& bmiHeader=*bitmap.GetBMI();
		BITMAPINFO& bmInfo=*(BITMAPINFO*)bitmap.GetBMI();
		LPVOID lpDIBBits = (LPVOID)((LPDWORD)(bmInfo.bmiColors + 
		                      bmInfo.bmiHeader.biClrUsed) + 
				((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0));
		CClientDC dc(NULL);
		HBITMAP hBmp=CreateDIBitmap(dc.m_hDC, &bmiHeader, CBM_INIT, lpDIBBits,
		                            &bmInfo, DIB_RGB_COLORS);

		CBitmap bmp;
		// add the thumbnail to the image list
		int imgPos=pView->m_imageList.Add(&bmp, RGB(0, 0, 0));
		pView->GetListCtrl().SetItem(itemIndex, 0, LVIF_IMAGE, NULL, imgPos,
		                             0, 0, 0);

	return 0;

The code uses SDK semaphores, pipes and threads because they are easier to handle and much straightforward than MFC threads and synchronization mechanisms.

The code is quite easy to follow and change to meet your needs, but if you need assistance, contact me. Also please send me bugs or updates, to keep this solution up-to-date. For more details on the sample application, contact me.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Web Developer
Romania Romania
... coming in a short while

Comments and Discussions

QuestionSource Code, Please Pin
Mike Marquet5-Nov-15 1:23
memberMike Marquet5-Nov-15 1:23 
QuestionYou're amazing! Nice demo ! Just as l expected! Pin
Member 1190182611-Aug-15 5:24
memberMember 1190182611-Aug-15 5:24 
QuestionSource code, Please. Pin
neoosk29-May-14 18:32
memberneoosk29-May-14 18:32 
QuestionSource code please! Pin
Member 107349208-Apr-14 17:11
memberMember 107349208-Apr-14 17:11 
QuestionSource Code, please Pin
Luigidor7-Mar-14 22:51
memberLuigidor7-Mar-14 22:51 
GeneralSource Code ,Please Pin
chenmeshine1-Dec-13 14:42
memberchenmeshine1-Dec-13 14:42 
QuestionSource code, Please Pin
Rua Naruto28-Nov-13 19:40
memberRua Naruto28-Nov-13 19:40 
GeneralMy vote of 1 Pin
KarstenK24-Oct-13 3:08
mveKarstenK24-Oct-13 3:08 
QuestionSince This Dude Is A Joke Pin
xox_c0bra_xox20-Nov-12 1:42
memberxox_c0bra_xox20-Nov-12 1:42 
AnswerRe: Since This Dude Is A Joke Pin
haithink9-Dec-13 15:29
memberhaithink9-Dec-13 15:29 
GeneralMy vote of 5 Pin
Member 143041112-Oct-10 3:07
memberMember 143041112-Oct-10 3:07 
GeneralSource Code Pin
jisha1220-Sep-10 2:00
memberjisha1220-Sep-10 2:00 
GeneralPlease send your code Pin
Sudhakara Rao N21-Jul-10 8:22
memberSudhakara Rao N21-Jul-10 8:22 
GeneralHey,please send me the sorce code... Pin
xiyuefeng12-Jun-10 21:10
memberxiyuefeng12-Jun-10 21:10 
GeneralPlease send me the source code Pin
Johncuicui31-May-10 21:02
memberJohncuicui31-May-10 21:02 
GeneralPlease send me the source code Pin
zq_lanqiu15-Apr-10 21:07
memberzq_lanqiu15-Apr-10 21:07 
GeneralPlease, Send me Source Code Pin
vicaljin26-Jan-10 0:19
membervicaljin26-Jan-10 0:19 
Generalplease send me source code Pin
GloryHan22-Jan-10 1:38
memberGloryHan22-Jan-10 1:38 
GeneralThe Source Code , Please Pin
jordan_guo14-Nov-09 19:09
memberjordan_guo14-Nov-09 19:09 
GeneralCould you send me the source Pin
jordan_guo21-Oct-09 4:59
memberjordan_guo21-Oct-09 4:59 
GeneralI am very insterted in your work Pin
wangshumin27-Sep-09 3:20
memberwangshumin27-Sep-09 3:20 
GeneralSource code please, Thanks Pin
Techice24-Sep-09 23:05
memberTechice24-Sep-09 23:05 
Generalsource code please(09/18/2009) Pin
JamesDK17-Sep-09 21:01
memberJamesDK17-Sep-09 21:01 
Generalcode Pin
mabin20103-Sep-09 19:25
membermabin20103-Sep-09 19:25 
GeneralPlease Help me [modified] Pin
Sheela Gusain3-Jul-09 19:44
memberSheela Gusain3-Jul-09 19:44 

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.

Posted 4 Jan 2000


128 bookmarked