上一篇提完了重绘了CListViewCtrl,后来我想不需要网格线,结果发现一个问题,如果加双缓冲之后,不管怎么样都会有网格线,在网上又找了好久,发现一篇可以重改网络线颜色的日志,于是想到一个有意思的方法。复制竖线右侧一个像素的到左侧,完成效果。
原样式:

修改后样式:

响应Print消息,代码如下:
LRESULT CMdListViewCtrl::OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
//// TODO: 在此添加消息处理程序代码和/或调用默认值
DefWindowProc();
// Draw the lines only for LVS_REPORT mode
if( (GetStyle() & LVS_TYPEMASK) == LVS_REPORT )
{
// Get the number of columns
CClientDC dc(this->m_hWnd);
RECT rect;
//this->GetClientRect(&rect);
//dc.FillRect(&rect,RGB(255,255,255));
int nColumnCount = m_headerCtrl.GetItemCount();
// The bottom of the header corresponds to the top of the line
//RECT rect;
m_headerCtrl.GetClientRect( &rect );
int top = rect.bottom;
// Now get the client rect so we know the line length and
// when to stop
GetClientRect( &rect );
// The border of the column is offset by the horz scroll
int borderx = 0 - GetScrollPos( SB_HORZ );
dc.SelectPen((HPEN)GetStockObject(DC_PEN));
dc.SetDCPenColor(RGB(255,255,255));
for( int i = 0; i < nColumnCount; i++ )
{
// Get the next border
borderx += GetColumnWidth( i );
// if next border is outside client area, break out
if( borderx >= rect.right ) break;
// Draw the line.
dc.BitBlt( borderx, top, 1, rect.bottom - rect.top, dc , borderx + 1, top, SRCCOPY);
//dc.MoveTo( borderx, top);
//dc.LineTo( borderx, rect.bottom );
}
// Draw the horizontal grid lines
// First get the height
if( !GetItemRect( 0, &rect, LVIR_BOUNDS ))
return 0;
int height = rect.bottom - rect.top;
GetClientRect( &rect );
int width = rect.right;
//dc.SelectPen((HPEN)GetStockObject(DC_PEN));
dc.SetDCPenColor(RGB(170,170,170));
for( int i = 1; i <= GetCountPerPage(); i++ )
{
dc.MoveTo( 0, top + height*i-1);
dc.LineTo( width, top + height*i-1 );
}
}
return 0;
}
另外还重绘了表头,使用了以下类:
class CMdHeader:public CWindowImpl<CMdHeader,CHeaderCtrl>, public COwnerDraw<CMdHeader>
{
public:
BEGIN_MSG_MAP(CMdHeader)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
//MESSAGE_HANDLER(WM_MEASUREITEM, OnMeasureItem)
MESSAGE_HANDLER(HDM_LAYOUT, OnHDMLayout)
CHAIN_MSG_MAP_ALT(COwnerDraw<CMdHeader>, 1) //将消息反射给自己 1 有父类处理消息 0
DEFAULT_REFLECTION_HANDLER()
END_MSG_MAP()
public:
CMdHeader()
{
m_nHeight = 25;
}
~CMdHeader()
{
}
public:
int m_nHeight;
LRESULT OnPaint(UINT , WPARAM , LPARAM , BOOL& )
{
CPaintDC dc(m_hWnd);
RECT rect,rectItem;
::GetClientRect(m_hWnd,&rect);
//TRIVERTEX tv[] = {
// { rect.left, rect.top,0x8500,0x8500,0x8500},
// { rect.right, rect.bottom-13, 0x5a00,0x5a00,0x5a00}
//};
//GRADIENT_RECT gr = { 0, 1 };
//dc.GradientFill ( tv, 2, &gr, 1, GRADIENT_FILL_RECT_V );
//TRIVERTEX tvs[] = {
// { rect.left, rect.top+15,0,0,0},
// { rect.right, rect.bottom, 0,0,0}
//};
//dc.GradientFill ( tvs, 2, &gr, 1, GRADIENT_FILL_RECT_V );
dc.FillSolidRect(&rect, RGB(255, 255, 255));
dc.MoveTo(0,rect.bottom-1);
dc.LineTo(rect.right,rect.bottom-1);
int nItems = GetItemCount();
HDITEM hdi;
TCHAR lpBuffer[256]={0};
UINT uFormat = DT_SINGLELINE|DT_CENTER|DT_VCENTER;//DT_SINGLELINE | DT_NOPREFIX | DT_TOP |DT_CENTER | DT_END_ELLIPSIS;
dc.SelectFont( HFONT( GetStockObject( DEFAULT_GUI_FONT)));
for(int i = 0;i<nItems;i++) //最后一个分割标志不用画
{
GetItemRect(i, &rectItem);
hdi.mask = HDI_TEXT;
hdi.pszText = lpBuffer;
hdi.cchTextMax = 256;
GetItem(i, &hdi);
dc.SetTextColor(RGB(0,0,0));
dc.SetBkMode(TRANSPARENT);
CString str = lpBuffer;
dc.DrawText(str,str.GetLength(),&rectItem,uFormat);
memset(lpBuffer,0,256);
}
return 0;
}
LRESULT OnHDMLayout(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
LRESULT lResult = CWindowImpl<CMdHeader, CHeaderCtrl>::DefWindowProc(uMsg, wParam, lParam);
HD_LAYOUT &hdl = *( HD_LAYOUT * ) lParam;
RECT *prc = hdl.prc;
WINDOWPOS *pwpos = hdl.pwpos;
int nHeight = (int)(pwpos->cy);
if(m_nHeight>=0)
nHeight = m_nHeight;
pwpos->cy = nHeight;
prc->top = nHeight;
return lResult;
}
//LRESULT OnMeasureItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
//{
// LPMEASUREITEMSTRUCT lpMeasureItemStruct = (LPMEASUREITEMSTRUCT)lParam;
// lpMeasureItemStruct->itemHeight = 25;
// return (LRESULT)TRUE;
//}
void DrawItem(LPDRAWITEMSTRUCT lpdis)
{
//::MessageBox(NULL,L"qqq",L"111",MB_OK);
}
void DeleteItem(LPDELETEITEMSTRUCT lpdis)
{
}
void SetStyle()
{
HDITEM hdItem;
hdItem.mask = HDI_FORMAT;
for(int i=0; i<this->GetItemCount(); i++)
{
this->GetItem(i,&hdItem);
hdItem.fmt|= HDF_OWNERDRAW;
this->SetItem(i,&hdItem);
}
CFont m_NewHeaderFont;
m_NewHeaderFont.CreatePointFont(300,L"宋体");
this->SetFont(m_NewHeaderFont);
m_NewHeaderFont.DeleteObject();
//ModifyStyle(HDS_BUTTONS, 0);
}
};在::OnCreate子类化:
//子类化表头
m_headerCtrl.SubclassWindow(this->GetHeader().m_hWnd);
m_headerCtrl.SetStyle();在使用WIN7编译时,还遇到一个问题,VS2008在编译时总报错误,在网上到到解决方法:
错误:LINK : fatal error LNK1000: Internal error during IncrBuildImage
解决办法:
项目->属性->链接器->常规 下面的“启用增量链接”,将“是(/INCREMENTAL)”改为“否(/INCREMENTAL:NO)”。
不过这又引入了另外一个警 告:FormatCom.obj : warning LNK4075: 忽略“/EDITANDCONTINUE”(由于“/INCREMENTAL:NO”规范)
选择项目,属性->配置属性 ->C/C++,修改“调试信息格式”为“程序数据库(/Zi)”即可。
到此问题解决,据说这是VC的一个内部BUG,可以下载KB948127补丁来解决,但我并没有能正常安装该补丁。
下载补丁地址:http://code.msdn.microsoft.com/KB948127
虽然不然安装,但是我从这个补丁中提取出了link.exe替换相应文件,问题解决。
我把这个link.exe上传到资源:http://download.csdn.net/detail/lymcn/3859078
在上一篇博客中介绍了CListViewCtrl的重绘,但发现无法去除网格线。通过查找资料,找到了一种巧妙的方法:复制竖线右侧像素至左侧实现效果。文章详细讲述了实现过程,包括响应Print消息的代码,并解决了链接错误LNK1000的问题。通过调整链接器设置和C/C++的调试信息格式,成功解决警告。虽未能安装KB948127补丁,但从补丁中提取link.exe文件解决了问题。资源链接已提供。
重绘CListViewCtrl之二&spm=1001.2101.3001.5002&articleId=7025077&d=1&t=3&u=3902dab1c5944ad4bc8d911cadd9432e)
7296

被折叠的 条评论
为什么被折叠?



