CListBox class can contain string data type as well as Icons.
In fact in Windows all controls are considered to be a window
with their own Message Maps, Screen formatting functions etc.,
Most of these controls are derived from the parent CWnd
classes and hence inherit all the abilities as stated above. This article " CListBox example using Icons "
explains how to use a CListBox class for displaying Icons as
well as text.
Creating
the Derived Class - CListBox example using Icons:
An MFC application has to be created first. Before doing anything on the application, we need to
derive a Custom List Box class with Fixed Owner Draw
property enabled. That means, the derived CListBox class
should be able to handle the DrawItem by itself. It should
also set the measurements properly using MeasureItem function.
To derive a new class based on an MFC class do the following.
- Open
the Class Wizard of the project where the new class
has to be derived for CListBox example.
- Click
on the Add Class command button.
- Give
the name of the new class and select the base class as
CListBox
- Use
the sample below to fill out the functions needed.
- The
derived class must be added with the functions
DrawItem and MeasureItem using, the Class Wizard.
This will enable the new CListBox derived class to have its
own behavior of drawing items.
This sample assumes that two icons are created in the project
with ids IDI_ICON1, IDI_ICON2.
CImageList g_Image_List;
/////////////////////////////////////////////////////////////////////////////
// MyListBox constructor for CListBox example
MyListBox::MyListBox()
{
BOOL
bRet = FALSE;
HICON hIcon = NULL;
// Create image list. This can be used for CListBox
example
bRet = g_Image_List.Create(16, 16, ILC_COLOR32 | ILC_MASK,
5, 1);
ASSERT(bRet == TRUE);
// Add some icons
hIcon = AfxGetApp()->LoadIcon(IDI_ICON1);
g_Image_List.Add(hIcon);
// Add some icons
hIcon = AfxGetApp()->LoadIcon(IDI_ICON2);
g_Image_List.Add(hIcon);
}
//Destructor of the derived class for CListBox example
MyListBox::~MyListBox()
{
}
void
MyListBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO: Add your code to draw the specified item
//CRect members to store the position of the items
CRect rItem;
CRect rText;
CRect rIcon;
CDC* dc = CDC::FromHandle(lpDrawItemStruct->hDC);
if ((int)lpDrawItemStruct->itemID
< 0)
{
// If there are no elements in the List Box
// based on whether the list box has Focus or not
// draw the Focus Rect or Erase it,
if ((lpDrawItemStruct->itemAction & ODA_FOCUS) && (lpDrawItemStruct->itemState
& ODS_FOCUS))
{
dc->DrawFocusRect(&lpDrawItemStruct->rcItem);
}
else if
((lpDrawItemStruct->itemAction & ODA_FOCUS) && !(lpDrawItemStruct->itemState
& ODS_FOCUS))
{
dc->DrawFocusRect(&lpDrawItemStruct->rcItem);
}
return;
}
// String to store the text,
which will be added to the CListBox
CString strText;
// Get the item text.
GetText(lpDrawItemStruct->itemID, strText);
//Initialize the Item's row
rItem = lpDrawItemStruct->rcItem;
//The icon that the sample has
created has a width of 16 pixels
rIcon = lpDrawItemStruct->rcItem;
rIcon.bottom = rIcon.top + 16;
rIcon.right = rIcon.left + 16;
//Start drawing the text 2 pixels
after the icon
rText.left = rIcon.right + 2;
rText.top = rIcon.top;
UINT nFormat = DT_LEFT | DT_SINGLELINE |
DT_VCENTER;
if (GetStyle() & LBS_USETABSTOPS)
nFormat |=
DT_EXPANDTABS;
// If item selected, draw the highlight
rectangle.
// Or if item deselected, draw the
rectangle using the window color.
if ((lpDrawItemStruct->itemState &
ODS_SELECTED) && (lpDrawItemStruct->itemAction & (ODA_SELECT |
ODA_DRAWENTIRE)))
{
CBrush
br(::GetSysColor(COLOR_HIGHLIGHT));
dc->FillRect(&rItem,
&br);
}
else if (!(lpDrawItemStruct->itemState &
ODS_SELECTED) &&
(lpDrawItemStruct->itemAction & ODA_SELECT))
{
CBrush
br(::GetSysColor(COLOR_WINDOW));
dc->FillRect(&rItem, &br);
}
// If the item has focus, draw the focus
rect.
// If the item does not have focus, erase
the focus rect.
if ((lpDrawItemStruct->itemAction &
ODA_FOCUS) && (lpDrawItemStruct->itemState & ODS_FOCUS))
{
dc->DrawFocusRect(&rItem);
}
else if ((lpDrawItemStruct->itemAction &
ODA_FOCUS) && !(lpDrawItemStruct->itemState & ODS_FOCUS))
{
dc->DrawFocusRect(&rItem);
}
// To draw the Text set the background mode
to Transparent.
int iBkMode = dc->SetBkMode(TRANSPARENT);
COLORREF crText;
if (lpDrawItemStruct->itemState &
ODS_SELECTED)
crText = dc->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
else if (lpDrawItemStruct->itemState &
ODS_DISABLED)
crText = dc->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));
else
crText = dc->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
CPoint pt(rIcon.left,rIcon.top);
g_Image_List.Draw(dc,0,pt,ILD_NORMAL);
dc->TextOut(rText.left,rText.top,strText);
dc->SetTextColor(crText);
}
void
MyListBox::MeasureItem(LPMEASUREITEMSTRUCT
lpMeasureItemStruct)
{
//
TODO: Add your code to determine the size of specified
item
//The sample icons are created with height of 16 pixels
lpMeasureItemStruct->itemHeight = 16;
}
The
rest of the functions of the CListBox derived class need not be changed.
DrawItem function takes care of drawing the Text and the Icon.
It also handles the changes of color in case of Text selected
and deselected. If the new derived class is used for the List
box resource, it can handle the Icons.
Creating
the MFC Application - CListBox example using Icons:
Follow the steps to use the MyListBox derived from CListBox
with customizations.
-
Create a MFC Dialog based application with a List Box
Resource.
- In
the Properties dialog of the List Box in the
Styles tab,
check Has Strings Check box.
- In
the Owner Draw Combo, select Fixed. Keep all the other options
unchanged.
- Add
two Icons to the application with IDs
IDI_ICON1 and IDI_ICON2.
-
Ensure that the above functions of MyListBox::MyListBox
constructor, MyListBox::DrawItem and MyListBox::MeasureItem
are copied into the new derived class.
- In
the InitDialog function of the dialog class, use the
following code or replace with your own values.
m_MyListBox.AddString("CListBox Example with Icon 1");
m_MyListBox.AddString("CListBox Example with Icon 2");
7. Compile and Run the application.
Any control which needs some kind of custom features like this
will need to be inherited and some functions have to be
overridden.
The above sample should create a dialog box with a list box
containing icons and the text typed in. Refer the
mfc
tutorial sample for source code.
Summary
- CListBox example using Icons:
To add
Icons to a list box,
- A new
list box class should be derived from CListBox
- DrawItem
and MeasureItem functions have to be overridden.
- A
CImageList class can be used to hold the list of Icons.
- The
derived class should be used for manipulating the List Box
resource.