Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

CWnd/WTL based HTML List Control with different row heights

0.00/5 (No votes)
2 May 2006 4  
This is a CWnd/WTL based list control; it supports basic HTML tags and multiple row heights.

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:

//Dimentions for the list ctrl

CRect rcList(10,10,400,400);
m_list.Create(this,rcList,123/*Control Id*/); 

//Add imagelist if we want to display images

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)
   //{{AFX_MSG_MAP(CMyDlg)

   .
   .
   ON_NOTIFY(HTMLLIST_SELECTIONCHANGED,
         123/*list id*/,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)
   {
      //Draw individual items yourself

      ......
   }
}

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
    • Initial release.

License

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