Date: | July 13, 2005 / year-entry #188 |
Tags: | code |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20050713-12/?p=34953 |
Comments: | 5 |
Summary: | One of the things that is interesting to me as a student of the Chinese languages is to recognize where the traditional and simplified Chinese scripts differ. Since this is my program, I'm going to hard-code the color for simplified Chinese script: maroon. To accomplish the highlighting, we take advantage of listview's custom-draw feature. Custom-draw... |
One of the things that is interesting to me as a student of the Chinese languages is to recognize where the traditional and simplified Chinese scripts differ. Since this is my program, I'm going to hard-code the color for simplified Chinese script: maroon. To accomplish the highlighting, we take advantage of listview's custom-draw feature. Custom-draw allows you to make minor changes to the way items are displayed on the screen. It's a middle ground between having listview do all the work (via default drawing behavior) and having the program do all the work (via owner-draw).
The custom-draw cycle for shell common controls consists of
series of
Listviews are peculiar among the shell common controls in that
its items sometimes (but not always) have sub-items.
This complicates the drawing process since it requires listview
to accomodate both styles:
large icon view does not use sub-items, but report view does.
To address this, the With those preliminary remarks settled, we can dive in. class RootWindow : public Window { ... protected: ... LRESULT OnLVCustomDraw(NMLVCUSTOMDRAW* pcd); ... private: HWND m_hwndLV; COLORREF m_clrTextNormal; Dictionary m_dict; }; We declare our listview custom-draw handler as well as the member variable in which we remember the normal text color so that we can reset it for columns we do not intend to colorize. LRESULT RootWindow::OnNotify(NMHDR *pnm) { switch (pnm->code) { case LVN_GETDISPINFO: OnGetDispInfo(CONTAINING_RECORD(pnm, NMLVDISPINFO, hdr)); break; case NM_CUSTOMDRAW: if (pnm->hwndFrom == m_hwndLV) { return OnLVCustomDraw(CONTAINING_RECORD( CONTAINING_RECORD(pnm, NMCUSTOMDRAW, hdr), NMLVCUSTOMDRAW, nmcd)); } break; } return 0; }
If we receive a
LRESULT RootWindow::OnLVCustomDraw(NMLVCUSTOMDRAW* pcd) { switch (pcd->nmcd.dwDrawStage) { case CDDS_PREPAINT: return CDRF_NOTIFYITEMDRAW; case CDDS_ITEMPREPAINT: m_clrTextNormal = pcd->clrText; return CDRF_NOTIFYSUBITEMDRAW; case CDDS_ITEMPREPAINT | CDDS_SUBITEM: pcd->clrText = m_clrTextNormal; if (pcd->iSubItem == COL_SIMP && pcd->nmcd.dwItemSpec < (DWORD)Length()) { const DictionaryEntry& de = Item(pcd->nmcd.dwItemSpec); if (de.m_pszSimp) { pcd->clrText = RGB(0x80, 0x00, 0x00); } } break; } return CDRF_DODEFAULT; }
During the First, we reset the color to the default on the assumption that we will not need to colorize this column. But if the column is the simplified Chinese column, if the item number is valid, and if the simplified Chinese is different from the traditional Chinese, then we set the text color to maroon. That's enough with the Chinese/English dictionary for now. All this time, and we don't even have search capability yet! We'll work on that next month. |
Comments (5)
Comments are closed. |
Since this will probably rise to the top of Google’s results concerning list-view custom draw, let me add that on a dialog, you can’t just return CDRF_NOTIFYITEMDRAW, due to the way dialog procs work (as Raymond has discussed elsewhere).
Instead, set the return value in the dialog using SetWindowLongPtr and DWL_MSGRESULT, as in the following snippet:
switch (lvcd->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
SetWindowLongPtr(hwnd, DWL_MSGRESULT, CDRF_NOTIFYITEMDRAW);
return TRUE;
//…
}
Why use CONTAINING_RECORD rather than a cast?
The NMHDR structure’s base address is the same as the containing NMLVCUSTOMDRAW structure’s base address (NMHDR is the first member of the first member of the NMLVCUSTOMDRAW), so you can cast it directly, in this case.
But only in this case, and not if Microsoft changes one of the structures in the future (though that would break every existing program that uses them, so it likely won’t happen). Still, IMO it’s a bit cleaner.
NMHDR and the related NMxxx structs were designed to be castable, no? Sort of like a simple version of inheritance that’s usable from C?
Shameless plug for my own list view custom draw article: http://www.codeproject.com/listctrl/lvcustomdraw.asp
Changing the font on a column-by-column basis.