前提:采用report模式
1. 在CCtrlList的重写类中绑定事件
ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomdraw)
2. 在Dialog中绑定事件
ON_NOTIFY ( NM_CUSTOMDRAW, IDC_MY_LIST, OnCustomdrawMyList )
在OnCustomdrawMyList中调用CCtrlList的重写类的OnCustomdraw
3. 在重写类的OnCustomdraw中实现要单独绘制的内容了
注意:消息流为
LPNMLVCUSTOMDRAW lpnmcd = (LPNMLVCUSTOMDRAW) pNMHDR; switch(lpnmcd->nmcd.dwDrawStage) { case CDDS_PREPAINT: // 首个消息:通知listctrl重绘,返回逐个item绘制 { *pResult = CDRF_NOTIFYITEMDRAW; break; } case CDDS_ITEMPREPAINT: // 第二个消息:通知绘制item,返回逐个绘制sub-item { *pResult = CDRF_NOTIFYSUBITEMDRAW; break; } case CDDS_ITEMPREPAINT|CDDS_SUBITEM: // 第三个消息:绘制subitem { if (lpnmcd->iSubItem == 1/2/3/4) {// 在里面添加自己定义的绘制,可以使用传入结构体重的hdc和子项的rect范围等 *pResult = CDRF_SKIPDEFAULT; // 子绘制项指示绘制完毕,不许缺省绘制 } } }
以下为转载内容,翻译/写的非常好,是我个人主要参考的文章,非常推荐。
文章来源:http://blog.csdn.net/dylgsy/article/details/818550
NM_CUSTOMDRAW
),就可以让Windows为你干活了,你就不用被逼去处理"重绘过程"中所有的脏活了。
NM_CUSTOMDRAW
消息,你只需要添加一个处理函数以便开始使用Custom draw。首先添加一个消息映射,象下面一样:
ON_NOTIFY ( NM_CUSTOMDRAW, IDC_MY_LIST, OnCustomdrawMyList )
afx_msg void OnCustomdrawMyList ( NMHDR* pNMHDR, LRESULT* pResult );
WM_NOTIFY
消息,ID为
IDC_MY_LIST
,通知码为
NM_CUSTOMDRAW
,
OnCustomdrawMyList
就是你的处理函数。
ON_NOTIFY_REFLECT
来代替。如下:
ON_NOTIFY_REFLECT ( NM_CUSTOMDRAW, OnCustomdraw )
CListCtrl::SetItemData
所设的那个值
void CPanel1::OnCustomdrawList ( NMHDR* pNMHDR, LRESULT* pResult ) { NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );
// Take the default processing unless we set this to something else below. *pResult = 0;
// First thing - check the draw stage. If it's the control's prepaint // stage, then tell Windows we want messages for every item. if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage ) { *pResult = CDRF_NOTIFYITEMDRAW; } else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage ) { // This is the prepaint stage for an item. Here's where we set the // item's text color. Our return value will tell Windows to draw the // item itself, but it will use the new color we set here. // We'll cycle the colors through red, green, and light blue. COLORREF crText;
if ( (pLVCD->nmcd.dwItemSpec % 3) == 0 ) crText = RGB(255,0,0); else if ( (pLVCD->nmcd.dwItemSpec % 3) == 1 ) crText = RGB(0,255,0); else crText = RGB(128,128,255);
// Store the color back in the NMLVCUSTOMDRAW struct. pLVCD->clrText = crText;
// Tell Windows to paint the control itself. *pResult = CDRF_DODEFAULT; } }
结果如下,你可以看到行和行间的颜色的交错显示,多酷,而这只需要两个if的判断就可以做到了。
void CPanel3::OnCustomdrawList ( NMHDR* pNMHDR, LRESULT* pResult ) { NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR ); *pResult = 0; // If this is the beginning of the control's paint cycle, request // notifications for each item. if ( CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage ) { *pResult = CDRF_NOTIFYITEMDRAW; } else if ( CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage ) { // This is the pre-paint stage for an item. We need to make another // request to be notified during the post-paint stage. *pResult = CDRF_NOTIFYPOSTPAINT; } else if ( CDDS_ITEMPOSTPAINT == pLVCD->nmcd.dwDrawStage ) { // If this item is selected, re-draw the icon in its normal // color (not blended with the highlight color). LVITEM rItem; int nItem = static_cast<int>( pLVCD->nmcd.dwItemSpec ); // Get the image index and state of this item. Note that we need to // check the selected state manually. The docs _say_ that the // item's state is in pLVCD->nmcd.uItemState, but during my testing // it was always equal to 0x0201, which doesn't make sense, since // the max CDIS_ constant in commctrl.h is 0x0100. ZeroMemory ( &rItem, sizeof(LVITEM) ); rItem.mask = LVIF_IMAGE | LVIF_STATE; rItem.iItem = nItem; rItem.stateMask = LVIS_SELECTED; m_list.GetItem ( &rItem ); // If this item is selected, redraw the icon with its normal colors. if ( rItem.state & LVIS_SELECTED ) { CDC* pDC = CDC::FromHandle ( pLVCD->nmcd.hdc ); CRect rcIcon; // Get the rect that holds the item's icon. m_list.GetItemRect ( nItem, &rcIcon, LVIR_ICON ); // Draw the icon. m_imglist.Draw ( pDC, rItem.iImage, rcIcon.TopLeft(), ILD_TRANSPARENT ); *pResult = CDRF_SKIPDEFAULT; } } }
重复,custom draw让我们可以做尽可能少的工作,上面的例子就是让Windows帮我们做完全部的工作,然后我们就重新对选择状态的Item的图标做重画,那就是我们看到的那个图标。执行结果如下:唯一的不足是,这样的方法会让你感觉到一点闪烁。因为图标被画了两次(虽然很快)。用Custom Draw代替Owner Draw