重载 DrawItem 函数或Onpaint函数
首先设置ListCtrl的风格 注意去掉网格线。因为我们自己去绘制的了所以不显示网格线了。
如下即使用REPORT风格的ListCtrl控件但是不显示网格线。
LVS_REPORT & ~LVS_EX_GRIDLINES
//listCtrl控件
CRect listRect;
GetClientRect(listRect);
m_listCtr.Create(WS_VISIBLE|WS_CHILD|LVS_REPORT ,CRect(0,0,0,0),this, ID_WND_LISTCTR_LIST);
DWORD dwStyle = m_listCtr.GetExtendedStyle();
dwStyle |= LVS_REPORT & ~LVS_EX_GRIDLINES </span>| LVS_EX_FULLROWSELECT| LVS_SHOWSELALWAYS | LVS_EX_HEADERDRAGDROP | LVS_EX_CHECKBOXES;
m_listCtr.SetExtendedStyle(dwStyle);
m_listCtr.SetTextColor(RGB(0,207,209));
下面要注意的是:
nHightPerLine设置一个初始值,该初始值为当ListCtrl无数据时里面的ItermRect即一个网格的高度。如果没插入数据时,GetItemRect(0,&item,LVIR_BOUNDS)是返回的FALSE.
CRect item;
int nHightPerLine=18;
if(GetItemRect(0,&item,LVIR_BOUNDS))
{
nHightPerLine=item.bottom-item.top;
}
网络上大部分是下面这样写的。导致如果没数据插入时,直接return了。导致画出来的是没有横线,只有纵线的。
if(!GetItemRect(0,&rect, LVIR_BOUNDS ))
return;
void CMyListCtrl::OnPaint()
{
CListCtrl::OnPaint();
// Do not call CListCtrl::OnPaint() for painting messages
const MSG *msg = GetCurrentMessage();
DefWindowProc( msg->message, msg->wParam, msg->lParam );
CClientDC dc(this );
CRect rect;
GetClientRect(&rect);
CHeaderCtrl* pHeader=(CHeaderCtrl*)GetDlgItem(0);
int nColumnCount=pHeader->GetItemCount();
CRect rectHead;
pHeader->GetClientRect(&rectHead);
if( (GetStyle() & LVS_TYPEMASK) == LVS_REPORT )
{
CPen penGrid;
penGrid.CreatePen(PS_SOLID,2,RGB(0,66,66));//颜色
CPen *oldPen=dc.SelectObject(&penGrid);
int borderx =0-GetScrollPos(SB_HORZ);
//取客户区域
CRect item;
int nHightPerLine=18;
if(GetItemRect(0,&item,LVIR_BOUNDS))
{
nHightPerLine=item.bottom-item.top;
}
//画纵向线
for( int i=0;i<nColumnCount;i++)
{
borderx+=GetColumnWidth(i);
if (borderx>rect.right)
{
break;
}
dc.MoveTo(borderx,rectHead.bottom);
dc.LineTo(borderx,rect.bottom);
}
//画横向线
for(int i = 0; i <= GetCountPerPage(); i++ )
{
dc.MoveTo(rect.left,rectHead.bottom+nHightPerLine*i+1);
dc.LineTo(borderx,rectHead.bottom+nHightPerLine*i+1);
}
dc.SelectObject(penGrid);
penGrid.DeleteObject();
}
}
效果如图。