Introduction
As a shareware developer I use a lot of custom controls and stuff to make the application pretty as well as useful. For my last project, I had to build a list control with all sorts of funky stuff happening in the list items and I thought it would be nice to have a list control that could render the individual item's text in HTML.
As we know the changing of row height in CListCtrl
is a real pain, funny methods like using large fonts and stuff exist but they are not pretty and largely of no use to me, so I decided to write the whole thing from scratch.
Using CHTMLListCtrl
is very easy just include the required headers and call Create
when you want to create it (typically in OnInitdialog
).
In the .h file declare a variable:
CHTMLListCtrl m_list;
In the .cpp file:
CRect rcList(10,10,400,400);
m_list.Create(this,rcList,123);
m_ImageList.Create(16,16,ILC_COLOR24|ILC_MASK,4,4);
m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON_TEST));
m_ImageList.Add(AfxGetApp()->LoadIcon(IDR_MAINFRAME));
m_list.SetImageList(&m_ImageList);
To insert items in the ListCtrl, use the InsertItem
function. It takes a few arguments:
int InsertItem(CString sText,UINT uiImage,
int nStyle=HTML_TEXT,int nHeight=AUTO);
sText
: The item text (it can be a simple text or a text with HTML tags depending on the nStyle
parameter).
uiImage
: The image number (if an ImageList
has been attached, otherwise 0).
nStyle
: You can specify HTML_TEXT
, NORMAL_TEXT
and SINGLE_LINE_TEXT
(SINGLE_LINE_TEXT
will end in ellipses if the text too long).
nHeight
: You can specify the height of this row or CHTMLListCtrl
will calculate it for you.
An example of InsertItem
:
CString sText =
"<font color=#ff0000><b>Red Bold Font are scary</b></font>";
m_list.InsertItem(sText,0,HTML_TEXT);
To further customize the control's behaviour, you can use the SetExtendedStyle
function:
m_list.SetExtendedStyle(HTMLLIST_STYLE_GRIDLINES|
HTMLLIST_STYLE_CHECKBOX|HTMLLIST_STYLE_IMAGES);
HTMLLIST_STYLE_GRIDLINES
: Shows/hides gray lines between the items.
HTMLLIST_STYLE_CHECKBOX
: Adds checkboxes to the items.
HTMLLIST_STYLE_IMAGES
: Adds images to the items (you have to set an ImageList
through the SetImageList
function for this to work).
To receive events, you need to handle the WM_NOTIFY
Windows message. CHTMLListCtrl
supports the following events:
HTMLLIST_SELECTIONCHANGED
: Fired when list selection changes.
HTMLLIST_LBUTTONDOWN
: Fired when the left mouse button is down.
HTMLLIST_RBUTTONDOWN
: Fired when the right mouse button is down.
HTMLLIST_LBUTTONDBLCLICK
: Fired when the control is double clicked.
HTMLLIST_ITEMCHECKED
: Fired when the check box state changes.
You will not be able to use the class wizard to handle these events, you will have to manually add the entry in the message map.
In the message map write the following:
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
.
.
ON_NOTIFY(HTMLLIST_SELECTIONCHANGED,
123,OnHTMLList_SelChanged)
END_MESSAGE_MAP()
Now add the function:
void CMyDlg::OnHTMLList_SelectionChanged(NMHDR* pNMHDR,
LRESULT*)
{
NM_HTMLLISTCTRL *pListNMHDr =
(NM_HTMLLISTCTRL*) pNMHDR;
if(pListNMHDr->nItemNo != NONE_SELECTED)
{
MessageBox(pListNMHDr->sItemText);
}
Extending the control's functionality
The DrawItem
function is implemented as a virtual
function, so users can derive from CHTMLListCtrl
and draw their own items, for example:
class CMyHTMLListCtrl : public CHTMLListCtrl
{
public:
void DrawItem(CDC *pDC,CRect rcItem,
HTMLLIST_ITEM *pItem,BOOL bSelected)
{
......
}
}
Credits
The HTML rendering code is taken from Ukkie9's excellent article.
The following points are taken from Ukkie9's article:
- The only supported tags are
<p>
, <br>
, <font>..</font>
, <b>..</b>
, <i>..</i>
, <u>..</u>
, <strong>..</strong>
, <em>..</em>
, <sub>..</sub>
and <sup>..</sup>
. The tags <strong>..</strong>
are equivalent to <b>..</b>
, and <em>..</em>
map to <i>..</i>
.
- The
<font>
tag is used only for changing the text color. It is also the only tag that can take a parameter, and this parameter should be "color
" with a value in the well known HTML hexadecimal notation. For example, "<font color='#ffff00'>
".
- With the exception of tags that take parameters (currently, only the
<font>
tag), there can be no spaces in the tags; <p>
is okay, but <p align='right'>
will be considered as two words "<p" and "align='right'>". That's right: when DrawHTML()
considers that something is not a valid HTML tag, it prints it as a word.
- Special characters like
<
and �
are not supported, you must type in the correct characters. That is, you can just use the characters "�" and "&" in the text, and "<" too.
CHTMLListCtrl
also uses the CMemDC
written by Keith Rules, which can be downloaded from here (it is also included in the zip files above).
History
- 26th April, 2006
CalculateItemHeight
bug fixed.
- WTL version added (thanks to Ernest Laurentin).
SetCursor
bug fixed.
- Resizing bug fixed.
- 23rd March, 2006
CFont
handle released in OnDestroy
.
Invalidate(FALSE);
added in OnSize
.
GetItemCount
function added (DUH).
- 17th March, 2006