一:custom draw
自行绘制 ClistCtrl 的列表项,可以利用列表框的 NM_CUSTOMDRAW 消息,该消息由控件向它的父窗口发送,告诉父窗口它的绘图操作。
如果绘图操作不需要父窗口参与,可以使用该控件的 ON_NOTIFY_REFLECT 宏处理它的 NM_CUSTOMDRAW 消息。
它的处理函数的参数中包含 NMHDR,在 CUSTOMDRAW 的通知下 NMHDR 可以被转换成为 NMLVCUSTOMDRAW 结构,该结构包含了列表控件中需要自绘区域的全部信息:
typedef struct tagNMLVCUSTOMDRAW { NMCUSTOMDRAW nmcd; // 包含客户自绘控件信息的结构 COLORREF clrText; // 列表视图显示文字的颜色 COLORREF clrTextBk; // 列表视图显示文字的背景色 } NMLVCUSTOMDRAW, *LPNMLVCUSTOMDRAW;
NMCUSTOMDRAW 结构定义如下:
typedef struct tagNMCUSTOMDRAWINFO { NMHDR hdr; // 含有通知信息的 NMHDR 结构 DWORD dwDrawStage; // 目前绘制的步骤 HDC hdc; // 设备上下文句柄 RECT rc; // 绘制的区域 DWORD dwItemSpec; // 绘制项的说明 UINT uItemState; // 当前项的状态 LPARAM lItemlParam // 应用程序定义的数据 } NMCUSTOMDRAW, FAR * LPNMCUSTOMDRAW;
NMLVCUSTOMDRAW.nmcd.dwDrawStage 字段,它主要包含以下几个枚举值:
自绘时,可以通过处理以上几个绘画阶段的通知来实现。
例子详细步骤:
CCoolListCtrl.h 文件中: afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult);//消息函数声明
CCoolListCtrl.cpp 文件中: // 消息映射宏中添加:ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
BEGIN_MESSAGE_MAP(CCoolListCtrl, CListCtrl) //{{AFX_MSG_MAP(CCoolListCtrl) ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw) //}}AFX_MSG_MAP END_MESSAGE_MAP()
// 消息处理函数实现:
///////////////////////////////////////////////////////////////////////////// // CCoolListCtrl message handlers
void CCoolListCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) { // TODO: Add your control notification handler code here NMLVCUSTOMDRAW* pLVCD = reinterpret_cast <NMLVCUSTOMDRAW*> ( pNMHDR );
*pResult = 0; // Request item-specific notifications if this is the // beginning of the paint cycle.
if ( CDDS_PREPAINT == pLVCD-> nmcd.dwDrawStage ) { *pResult = CDRF_NOTIFYITEMDRAW; } else if ( CDDS_ITEMPREPAINT == pLVCD-> nmcd.dwDrawStage ) { // This is the beginning of an item 's paint cycle. LVITEM rItem; int nItem = static_cast <int> ( pLVCD-> nmcd.dwItemSpec ); CDC* pDC = CDC::FromHandle ( pLVCD-> nmcd.hdc ); COLORREF crBkgnd; BOOL bListHasFocus; CRect rcItem; CRect rcText; CString sText; UINT uFormat;
bListHasFocus = ( this->GetSafeHwnd() == ::GetFocus() );
// Get the image index and selected/focused state of the // item being drawn. ZeroMemory ( &rItem, sizeof(LVITEM) ); rItem.mask = LVIF_IMAGE | LVIF_STATE; rItem.iItem = nItem; rItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED; this->GetItem ( &rItem );
// Get the rect that holds the item 's icon. this->GetItemRect ( nItem, &rcItem, LVIR_ICON );
// Draw the icon. uFormat = ILD_TRANSPARENT;
if ( ( rItem.state & LVIS_SELECTED ) && bListHasFocus ) uFormat |= ILD_FOCUS;
m_imagelist.Draw ( pDC, rItem.iImage, rcItem.TopLeft(), uFormat );
// Get the rect that bounds the text label. this->GetItemRect ( nItem, rcItem, LVIR_LABEL ); //把这行去掉就没有文字.
// Draw the background of the list item. Colors are selected // according to the item 's state.
if ( rItem.state & LVIS_SELECTED ) { if ( bListHasFocus ) { crBkgnd = GetSysColor ( COLOR_HIGHLIGHT ); pDC-> SetTextColor ( GetSysColor ( COLOR_HIGHLIGHTTEXT )); } else { crBkgnd = GetSysColor ( COLOR_BTNFACE ); pDC-> SetTextColor ( GetSysColor ( COLOR_BTNTEXT )); } } else { crBkgnd = GetSysColor ( COLOR_WINDOW ); pDC-> SetTextColor ( GetSysColor ( COLOR_BTNTEXT )); }
// Draw the background & prep the DC for the text drawing. Note // that the entire item RECT is filled in, so this emulates the full- // row selection style of normal lists. pDC-> FillSolidRect ( rcItem, crBkgnd ); pDC-> SetBkMode ( TRANSPARENT );
// Tweak the rect a bit for nicer-looking text alignment. rcText = rcItem; // Draw the text. sText = this->GetItemText ( nItem, 0 );
pDC-> DrawText ( sText, CRect::CRect(rcText.left+3,rcText.top,rcText.right,rcText.bottom+60), DT_VCENTER );
// Draw a focus rect around the item if necessary. if ( bListHasFocus && ( rItem.state & LVIS_FOCUSED )) { pDC-> DrawFocusRect ( rcItem ); }
*pResult = CDRF_SKIPDEFAULT; // We 've painted everything. } }
//创建列表控件:自绘样式、没有列头部、处理通知 m_ListCtrl.Create(LVS_OWNERDRAWFIXED | LVS_NOCOLUMNHEADER | LBS_NOTIFY, CRect(0,0,400,200), this, IDC_LISTCTRL );
// 可以使用 m_ListCtrl.SetExtendedStyle 设置扩展样式
// 用自己编写的函数设置图像列表
m_ListCtrl.SetImagelist(IDB_IMAGE);
// 用自己编写的函数设置列表项的行高,方法见文章《CListCtrl行高的修改》 m_ListCtrl.SetItemHeight(36);
// 插入项
m_ListCtrl.InsertItem(0, "Monroeville", 0); m_ListCtrl.InsertItem(1, "Hartford", 1); m_ListCtrl.InsertItem(2, "Redmond", 2);
BOOL CCoolListCtrl::SetImagelist(UINT uBitmap) { m_imagelist.DeleteImageList(); m_imagelist.Create(32, 32, ILC_COLOR24|ILC_MASK, 8, 1); CBitmap bitmap; bitmap.LoadBitmap(uBitmap); m_imagelist.Add(&bitmap, RGB(255,0,255));
return TRUE; }
或者用下面的方法:
CHeaderCtrl* pHeaderCtrl =(CHeaderCtrl*)m_ListCtrl.GetHeaderCtrl(); pHeaderCtrl->EnableWindow( FALSE ) ; (#add 此法禁用了头部,往往没什么用,因为经常需要点击头部排序)