CListCtrl自绘checkBox

本人资质愚钝,这个问题的时间跨度差不多半年时间,终于算是完全解决。那么开始吧,自绘CListCtrl必然是

在DrawItem里面了,所以派生一个CListCtrlEx是必然了。那个自绘的风格改成true.

//标记每个checkBox的状态,这个结构体保存了每个item的状态,所有的item会保存在一个vector里
struct ITEM_CHECK
{
 int item;                 //第几行
 int flag;                 //falg 0是空,1是被选中,-1是变灰
};

//简单写下,千万别复制拷贝。
class CListCtrlEx : public CListCtrl
{
         vector<ITEM_CHECK>      m_itemVector;    //保存所有item状态 
}

//重写InsertItem,每插入一个m_itemVector添加一个。
int CListCtrlCl::InsertItem(int nItem,LPCTSTR lpszItem)
{
 CListCtrl::InsertItem(nItem,lpszItem);

 LVCOLUMN   lvColumn;  
 TCHAR strChar[256];
 lvColumn.pszText=strChar;  
 lvColumn.cchTextMax=256 ;
 lvColumn.mask   = LVCF_TEXT;
 GetColumn(0, &lvColumn);
 if(CString(lvColumn.pszText)!=_T(""))   //如果首列有字,那么就不再绘制checkbox
 {
  return -1;
 }

 m_itemCheck.item=nItem;
 m_itemCheck.flag=0;
 m_itemVector.push_back(m_itemCheck);
                   return;
}
//自绘的DrawItem函数
void CListCtrlEx::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
                CDC* pDC = CDC::FromHandle(lpDIS->hDC);
                LVITEM lvi = {0};
                  lvi.mask = LVIF_STATE;//|LVIF_IMAGE;
                  lvi.stateMask = LVIS_FOCUSED | LVIS_SELECTED ;
                  lvi.iItem = lpDIS->itemID;
         if(!m_bIsCheckBox)                                                //ClistCtrl是否含有checkBox的开关。关系到列表的风格
 {
  return -1;
 }

 m_itemCount=GetItemCount();
 int Top=GetTopIndex();
 //int Total=GetItemCount();
 int Total=m_itemVector.size();                                    //modify,2010,9,10

 if(m_itemVector.empty()||nItem>Total-1)
 {
  return -1;
 }
 CRect rt;                                                     //得到rt的范围,在此范围内创建CheckBox
 GetItemRect(nItem,&rt,LVIR_LABEL);
 rt.top+=2;
 rt.bottom-=2;
 rt.right-=3;

 if(m_itemVector.at(nItem).flag==0)             
 {
  pDC->DrawFrameControl(&rt,DFC_BUTTON,DFCS_BUTTONCHECK);

 }else if(m_itemVector.at(nItem).flag==1)
 {
  pDC->DrawFrameControl(&rt,DFC_BUTTON,DFCS_CHECKED);
 }else
 {
  pDC->DrawFrameControl(&rt,DFC_BUTTON,DFCS_INACTIVE);
 }
}
//很简单就是用了CDC::DrawFrameControl画出CheckBox的三种不同状态。

//单击选中通过修改m_itemVector的item状态,来改变绘制的不同状态。
void CListCtrlEx:OnLButtonDown(UINT nFlags,CPoint point)
{
 //CBrush  bush(RGB(2,143,54));
 if(m_itemVector.empty())
 {
  return;
 }
 CRect  tempRect;                                          //list矩形
 CRect  headerRect;                                        //headerCtrl矩形
 int height=point.y;
 int itemHeight = 0;
 int iItem = 0;

 GetItemRect(0, tempRect, LVIR_BOUNDS);
 itemHeight= tempRect.Height();
 m_Header.GetItemRect(0, headerRect);
 iItem = (height - headerRect.Height())/itemHeight;    //减去表头的高度,得到点击的是第几个item

 GetSubItemRect(iItem, 0, LVIR_LABEL, tempRect);
 tempRect.left += 1;
 tempRect.top += 1;
 tempRect.right -= 1;
 tempRect.bottom -= 1;
 if(tempRect.PtInRect(point))
 {
  ITEM_CHECK  &itemCheck = m_itemVector.at(iItem);
  if(itemCheck.flag == 1)
  {
   itemCheck.flag = 0;
  }else if(itemCheck.flag == 0)
  {
   itemCheck.flag = 1;
  }
  InvalidateRect(tempRect, 0);
 
 }
 
 //int coloum=height/15;
 //   SetItemColor(1, 1, RGB(2,143,54));
}

//重要的一点在双击消息里响应单击消息,不这样的做的话,当用户点的快了成了双击,checkbox
//就会没反应,让用户觉得这个checkbox有时反应迟钝,这是很恼人的一件事。所以在双击消息里也弄好。
void CListCtrlEx::OnLButtonDblClk(UINT nFlags,CPoint point)
{
               OnLButtonDown( nFlags, point) ; //调用单击
}

原文地址:https://www.cnblogs.com/yuzhould/p/4454985.html