1、CListCtrl控件分为上下两部分,上面的标头位置为标头控件,下方是我们需要绘制的CListCtrl,标头控件我们需要继承CHeaderCtrl进行标头控件的重绘,然后在CListCtrl中我们子类化CHeaderCtrl控件
2、CHeaderCtrl控件高度设置,有两种方法1:通过SetFont强制撑大控件的高度 //创建字体 CFont Font; Font.CreatePointFont(m_uItemHeight,TEXT("宋体")); //设置字体 SetFont(&Font);2:通过HDM_LAYOUT消息修改高度,添加ON_MESSAGE(HDM_LAYOUT, OnLayout)LRESULT CSkinHeaderCtrl::OnLayout( WPARAM wParam, LPARAM lParam ){ LRESULT lResult = CHeaderCtrl::DefWindowProc(HDM_LAYOUT, 0, lParam); HD_LAYOUT &hdl = *( HD_LAYOUT * ) lParam; RECT *prc = hdl.prc; WINDOWPOS *pwpos = hdl.pwpos; int nHeight = 28; pwpos->cy = nHeight; prc->top = nHeight; return lResult;}上述代码中设置了控件的高度为28
3、重绘CListCtrl,先将Owner Draw Fixed设为true或者Create的时候添加LVS_OWNERDRAWFIXED属性,目的就是让控件能响应DrawItem从而实现自绘,此处需要注意,对于LVS_ICON风格,DrawItem不会被系统调用,不管是否添加LVS_OWNERDRAWFIXED属性,当然可以通过在WM_PAINT内进行绘制,不过这样会给Report带来诸多的麻烦,所以,我们通过模拟来实现LVS_ICON的绘制
4、CListCtrl高度的设置,因为CListCtrl并没有诸如SetItemHeight之类的函数进行节点高度的设置,所以我们必须自己实现这样的功能void CSkinListCtrl::SetItemHeight( int nHeight ){ m_nHeightItem = nHeight; CRect rcWin; GetWindowRect(&rcWin); WINDOWPOS wp; wp.hwnd = m_hWnd; wp.cx = rcWin.Width(); wp.cy = rcWin.Height(); wp.flags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER; SendMessage(WM_WINDOWPOSCHANGED, 0, (LPARAM)&wp);}同时添加ON_WM_MEASUREITEM_REFLECT消息反射void CSkinListCtrl::MeasureItem( LPMEASUREITEMSTRUCT lpMeasureItemStruct ){ if (m_nHeightItem>0) { lpMeasureItemStruct->itemHeight = m_nHeightItem; }}这里提到了消息发射,注意区分和消息映射的区别,关于消息反射的概念不做赘述,可以通过MSDN进行查阅
5、CListCtrl为我们提供了SetExtendedStyle函数可以添加CListCtrl的很多扩展属性,这里强调一点LVS_EX_CHECKBOXES会导致ON_WM_MEASUREITEM_REFLECT消息反射不被接收,LVS_EX_GRIDLINES会造成节点矩形不准确,所以,我们需要重载屏蔽这些属性DWORD CSkinListCtrl::SetExtendedStyle( DWORD dwNewStyle ){ if ( dwNewStyle & LVS_EX_CHECKBOXES ) { dwNewStyle &=~LVS_EX_CHECKBOXES; dwNewStyle &=~LVS_EX_GRIDLINES; } return __super::SetExtendedStyle(dwNewStyle);}
6、Check设置,因为我们上面屏蔽了LVS_EX_CHECKBOXES,所以默认情况下,当我们插入节点的时候,默认是被Check的,所以, 还需要重载四个InsertItem函数在里面默认将Check取消掉,例如int CSkinListCtrl::InsertItem( const LVITEM* pItem ){ int nResult = __super::InsertItem(pItem); SetCheck(pItem->iItem,FALSE); return nResult;}
7、关于标头控件节点的拖动,当我们将鼠标放在两个节点的交叉处,鼠标会变成拖动的样式,此时按住左键可以拉伸节点的宽度,但是很多时候我们不想让前面的几个进行拖动,这个时候,我们需要在CHeaderCtrl派生类中重载OnChildNotify函数BOOL CSkinHeaderCtrl::OnChildNotify(UINT uMessage, WPARAM wParam, LPARAM lParam, LRESULT * pLResult){ //变量定义 NMHEADER * pNMHearder=(NMHEADER*)lParam; //拖动消息 if ((pNMHearder->hdr.code==HDN_BEGINTRACKA)||(pNMHearder->hdr.code==HDN_BEGINTRACKW)) { //禁止拖动 if (pNMHearder->iItem<(INT)m_uLockCount) { *pLResult=TRUE; return TRUE; } } return __super::OnChildNotify(uMessage,wParam,lParam,pLResult);}其中m_uLockCount就是禁止拖动的个数,比如设置为2,则前面2个节点将不能拉伸宽度,我们可以在写一个方法//设置锁定VOID CSkinHeaderCtrl::SetLockCount(UINT uLockCount){ //设置变量 m_uLockCount=uLockCount; return;}