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的判斷就可以做到了。
- 在ListCtrl控件繪畫前處理NM_CUSTOMDRAW消息。
- 告訴Windows我們想對每個Item處理NM_CUSTOMDRAW消息。
- 當這些消息中的一個到來,告訴Windows我們想在每個SubItem的繪製前處理這個消息
- 當這些消息到達,我們就爲每個SubItem設置文字和背景的顏色。
- 對ListCtrl在“繪畫前”處理NM_CUSTOMDRAW消息。
- 告訴Windows我們想在每個Item被畫的時候獲得NM_CUSTOMDRAW消息。
- 當這些消息來臨,告訴Windows我們想在你畫完的時候獲取NM_CUSTOMDRAW消息。
- 當這些消息來到的時候,我們就重新畫每一個Item的圖標。
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;
}
}
}