The CListCtrlWithCustomDraw Class
In the OnCustomdraw for CListCtrlWithCustomDraw, I provide a generic handler for custom draw notifications. The bulk of the code is a switch statement on the draw stage we are up to (refer to my previous article). At each of the pre-paint stages, I call virtual functions to get color information, fonts required, and to take over (or augment) the drawing process. I also allow for extra drawing during the post-paint stages.
Let's look at the fleshed out OnCustomdraw function for CListCtrlWithCustomDraw:
void CListCtrlWithCustomDraw::OnCustomdraw(NMHDR* pNMHDR,LRESULT* pResult)
{
// first, lets extract data from
// the message for ease of use later
NMLVCUSTOMDRAW* pNMLVCUSTOMDRAW = (NMLVCUSTOMDRAW*)pNMHDR;
// we'll copy the device context into hdc
// but won't convert it to a pDC* until (and if)
// we need it as this requires a bit of work
// internally for MFC to create temporary CDC
// objects
HDC hdc = pNMLVCUSTOMDRAW->nmcd.hdc;
CDC* pDC = NULL;
// here is the item info
// note that we don't get the subitem
// number here, as this may not be
// valid data except when we are
// handling a sub item notification
// so we'll do that separately in
// the appropriate case statements
// below.
int nItem = pNMLVCUSTOMDRAW->nmcd.dwItemSpec;
UINT nState = pNMLVCUSTOMDRAW->nmcd.uItemState;
LPARAM lParam = pNMLVCUSTOMDRAW->nmcd.lItemlParam;
// next we set up flags that will control
// the return value for *pResult
bool bNotifyPostPaint = false;
bool bNotifyItemDraw = false;
bool bNotifySubItemDraw = false;
bool bSkipDefault = false;
bool bNewFont = false;
// what we do next depends on the
// drawing stage we are processing
switch (pNMLVCUSTOMDRAW->nmcd.dwDrawStage) {
case CDDS_PREPAINT:
{
// PrePaint
m_pOldItemFont = NULL;
m_pOldSubItemFont = NULL;
bNotifyPostPaint = IsNotifyPostPaint();
bNotifyItemDraw = IsNotifyItemDraw();
// do we want to draw the control ourselves?
if (IsDraw()) {
if (! pDC) pDC = CDC::FromHandle(hdc);
CRect r(pNMLVCUSTOMDRAW->nmcd.rc);
// do the drawing
if (OnDraw(pDC,r)) {
// we drew it all ourselves
// so don't do default
bSkipDefault = true;
}
}
}
break;
case CDDS_ITEMPREPAINT:
{
// Item PrePaint
m_pOldItemFont = NULL;
bNotifyPostPaint = IsNotifyItemPostPaint(nItem,nState,lParam);
bNotifySubItemDraw = IsNotifySubItemDraw(nItem,nState,lParam);
// set up the colors to use
pNMLVCUSTOMDRAW->clrText =
TextColorForItem(nItem,nState,lParam);
pNMLVCUSTOMDRAW->clrTextBk =
BkColorForItem(nItem,nState,lParam);
// set up a different font to use, if any
CFont* pNewFont = FontForItem(nItem,nState,lParam);
if (pNewFont) {
if (! pDC) pDC = CDC::FromHandle(hdc);
m_pOldItemFont = pDC->SelectObject(pNewFont);
bNotifyPostPaint = true; // need to restore font
}
// do we want to draw the item ourselves?
if (IsItemDraw(nItem,nState,lParam)) {
if (! pDC) pDC = CDC::FromHandle(hdc);
if (OnItemDraw(pDC,nItem,nState,lParam)) {
// we drew it all ourselves
// so don't do default
bSkipDefault = true;
}
}
}
break;
评论