Coded
Article: An Introduction to Custom Draw -- The TreeView Control
(By Damon
Chandler)
With
the release of IE3 (comctrl32 version 4.70) Windows introduced the powerful
way to customize the appearance of common controls. This new technology,
rightfully named Custom Draw, is light years beyond the owner-drawn hangover
from Windows 3.0. Custom Draw allows the developer to have complete
control over the appearance without the need to draw every aspect
of the control.
We all know that for most controls, Windows allows
what is called an owner-drawn style. This allows the developer to
customize appearance. The problem is that all of the
drawing is put on the weight of the developer. For example, to create
an owner-drawn ListView, one must map the WM_DRAWITEM and WM_MEASUREITEM
messages as usual. Then within these message handlers, the programmer
must code the entire drawing routine -- from the normal items, to the subitems,
to the selected and focussed items; all while maintaining text spacing
and the more difficult task of speed. In other words, it's a major
hassle!
With Custom Draw, the developer can selectively
choose which aspects to draw. If one chooses just to change the font,
then it's as simple as sending a message to Windows and selecting the new
font into the provided device context. At any time, the developer
may choose to let Windows do the default drawing, or completely skip the
default. This selective drawing has several advantages. To
change the color of a single list item requires absolutely no drawing code
whatsoever.
The thing to keep in mind is that Custom Draw is
nothing more than a fancy communication between you and Windows.
Windows sends you messages that drawing is about to begin (CDDS_PREPAINT).
You respond by telling Windows what drawing stages you want notification
of, in this case CDRF_NOTIFYITEMDRAW for each node. Windows then
responds by sending you messages corresponding to each node being drawn
(CDDS_ITEMPREPAINT). Finally, you change certain attributes, then
respond to Windows by telling it that you changed an attribute (CDRF_NEWFONT).
At any stage, you can tell Windows to do the default drawing (CDRF_DODEFAULT)
or not to draw anything at all which means you have complete control over
appearance (CDRF_SKIPDEFAULT).
To use the Custom
Draw service, you need to handle the WM_NOTIFY message and test the code
member of the NMHDR member of the NMCUSTOMDRAW structure
(sent as the LParam) for the NM_CUSTOMDRAW notification. Also, test
the hwndFrom member of the NMHDR to make sure the
notification corresponds to the target control. From there, simply
test the drawing stage and respond with the correct CDRF_* constant (response
flag). The following list describes the information conveyed
in each member of the NMCUSTOMDRAW structure (for TreeViews):
typedef
struct tagNMCUSTOMDRAWINFO
{
NMHDR hdr; <--- This
the the NMHDR structure that describes the sender
of the message and the actual type of notification
(we're looking for NM_CUSTONDRAW in thie case).
DWORD dwDrawStage; <---
This member reports the drawing stage of the
Custom Draw process (CDDS_*).
HDC hdc; <---
This member is a handle to the device context to draw on.
RECT rc; <---
This member is the rectangle of the particular Node
referred to by the dwItemSpec member.
DWORD dwItemSpec; <---
This member reports the HTREEITEM of the
current Node that is being drawn (use
TTreeNode::ItemId to compare).
UINT uItemState; <---
This member reports the state of the item
(e.g., selected, hot, focused, etc.). It can be
a combination of one or more of the CDIS_*
constants.
LPARAM lItemlParam; <---
extra information associated with each item
}
NMCUSTOMDRAW, FAR * LPNMCUSTOMDRAW;
KEYWORDS: WM_NOTIFY, Custom
Draw
REFERENCES: http://msdn.microsoft.com/library/sdkdoc/shellcc/commctls/CustDraw/CustDraw.htm
|