Click here to Skip to main content
Click here to Skip to main content
Go to top

Using a Virtual CListCtrl to Display Text and Bitmaps

, 9 Apr 2009
Rate this:
Please Sign up or sign in to vote.
Includes code to create a virtual list control that also displays bitmaps from files at run time.
BMPList.gif

Introduction

This article shows an example of using a list control to do the following:

  1. Access data object virtually
  2. Access bitmaps larger than the typical icon used in views
  3. Access bitmaps virtually from a filename

Background

My company, Rimage, manufactures high end CD, DVD, and Blu-ray production equipment. The software I work on specifically is called QuickDisc. It is the interface that helps desktop users collect files using drag and drop and select the options that they want to use when creating discs. Our equipment automatically loads the disc drives and prints on the disc using a printer we developed. I was given the task of adding a feature to QuickDisc that would show a bitmap (thumbnail) in a list control. 

In our case, there could be thousands of them so I didn't want to load them all into memory at the same time and certainly didn't want to host them all in the list control. I looked around for examples of loading bitmaps dynamically and found only a few so I decided to share this result.  The code is heavily commented and the techniques are pretty easy once figured out.

Using the Code/Points of Interest

This is just an example program so users could cut and paste any of the code into their own programs and tailor to their particular needs. I chose to use BMP files, but it would be a simple matter to use the CImage class to load any kind of graphic (JPG, PNG, etc.) and convert it to the ImageList format at run time. One of the nice things about a virtual list control is that only the data that is showing on the screen is actually in the control. The rest is neatly stored elsewhere in data collections or on the disc. Thus, the control does not slow down regardless of how many items are displayed.

The specific items of interest in the code are listed below. Note: I am not actually using the imagelists for anything besides a holding place for the eventual bitmaps.

 if(m_imageList.GetSafeHandle() == NULL) {
		m_imageList.Create(210, 160, ILC_COLOR24 | ILC_MASK, 8, 1);
		m_cList.SetImageList(&m_imageList, LVSIL_SMALL);
		m_cList.SetImageList(&m_imageList, LVSIL_NORMAL);
		m_imageList.SetImageCount(1);
	}	CString csFilePath = _T("C:\\TestFiles");

I am setting the number of items in the list control to the count in my corresponding data array. The list thinks it has this number of items even though I never actually loaded anything to it.

// This sets the count in the list without adding any items.  This is very fast.
m_cList.SetItemCountEx((int)m_MyDataArray.GetCount(),
     LVSICF_NOSCROLL|LVSICF_NOINVALIDATEALL);

This is the workhorse routine. It gets called by the list control for every line that it wants to display on the screen. Notice that there are two masks I am handling, 1 for the text and the other for the bitmap.

void CBMPListDlg::GetDispInfo(NMHDR *pNMHDR, LRESULT *pResult)
{
	NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);

	//Create a pointer to the item
	LV_ITEM* pItem= &(pDispInfo)->item;

	//Which item number?
	int nItem = pItem->iItem;

	CMyDataInfo *pInfo = NULL;
	if(nItem > m_MyDataArray.GetSize()-1)
		return; // Just to be safe

	pInfo = (CMyDataInfo *)m_MyDataArray.GetAt(nItem);
	if(pInfo == NULL)
		return;
    
	//Do we need text information?
	if (pItem->mask & LVIF_TEXT) {
		CString csText;

		//Which column?
		if(pItem->iSubItem == 0)
			csText = pInfo->m_csColumn1;
		else if (pItem->iSubItem == 1) // Column 1
			csText = pInfo->m_csColumn2;
		else if (pItem->iSubItem == 2) // Column 2
			csText = pInfo->m_csColumn3;
		else if (pItem->iSubItem == 3) // Column 3
			csText = pInfo->m_csColumn4;

		//Copy the text to the LV_ITEM structure
		//Maximum number of characters is in pItem->cchTextMax
		lstrcpyn(pItem->pszText, csText, pItem->cchTextMax);
	}

	//Does the list need image information?
	if( pItem->mask & LVIF_IMAGE) {
		// Need to reset first item of image list to the
                  // correct bitmap
		HBITMAP hBmp = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),
                                    	pInfo->m_csImage,
				IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
		if(hBmp != NULL) {
			CBitmap *cBmp = CBitmap::FromHandle(hBmp);
			if(cBmp != NULL)
				m_imageList.Replace(0,cBmp,NULL);
		}
		// Note, there is no Navigator 0.bmp so that image will
                 	// always display blank to 
		// illustrate what would happen when the file is not found.
		else {
			CBitmap *cBmp = new CBitmap();
			cBmp->LoadBitmap(IDB_BLANK);
			m_imageList.Replace(0,cBmp,NULL);
			delete cBmp;
		}
		pItem->iImage = 0; // Always use 0 since only one element
    }
	*pResult = 0;
}

History

  • Version 1.0 - April 5, 2009

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication

Share

About the Author

Thomas Serface
Software Developer (Senior)
United States United States
I have been using VC++ with MFC since it first came out circa 1993 and I saw it demonstrated at a local Software Development show. I've been working for Rimage Corporation for around 23 years developing software to make our CD and DVD publishing hardware work.
 
When I'm not working I enjoy hanging out with my family, playing guitar, traveling, and taking my dogs for walks. My family enjoys watching Survivor on Thursday nights and we're not even embarassed by it.

Comments and Discussions

 
QuestionMy vote 5 Pinmembertiger5491012-Apr-12 8:07 
GeneralMy vote of 4 Pinmemberbuyong18-Sep-11 19:25 
QuestionHow to display the image in 2nd or 3rd column? Pinmembereight12-Jul-10 17:34 
GeneralThanks for a nice simple example Pinmemberjefflewis11-Aug-09 1:49 
GeneralIt is very useful for me [modified] Pinmemberbrighttown21-Jul-09 19:38 
GeneralMy vote of 2 Pinmembersurajfrommumbai8-Apr-09 16:31 
GeneralRe: My vote of 2 PinmemberThomas Serface8-Apr-09 20:12 
GeneralRe: My vote of 2 PingroupShengGong3-Jan-10 21:03 
Questionwhy bitmap ? PinmemberLove In Snowing8-Apr-09 15:23 
AnswerRe: why bitmap ? Pinmemberbolivar1238-Apr-09 16:14 
AnswerRe: why bitmap ? PinmemberThomas Serface8-Apr-09 20:20 

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.140916.1 | Last Updated 9 Apr 2009
Article Copyright 2009 by Thomas Serface
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid