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) ; //调用单击
}