改变TListView的表格头部颜色
列表头实际上是一个SysHeader32控件,如果想改变它的颜色,唯一的办法就是自己画!那如何自己画呢?
1、首先,那个SysHeader32的每一个Item都必须具有HDF_OWNERDRAW属性。
2、当Item具有HDF_OWNERDRAW时,Windows在画它们之前将向SysHeader32的Owner(也就是TListView)发送WM_DRAWITEM消息,因此必须截获TListView的窗口过程检测消息WM_DRAWITEM然后自己画。
大概步骤如下:
1、定义变量和方法
TWndMethod OldLVWndProc;

void __fastcall NewLVWndProc(TMessage& Message);
2、在FormCreate中安装新的窗口过程
OldLVWndProc=LV1->WindowProc;
LV1->WindowProc=NewLVWndProc;

//设置属性
SetupColumnToOwnerDraw();

//-------------------------------------------
void __fastcall SetupColumnToOwnerDraw()
{
HWND HeaderHandle;
HD_ITEM hdi;

HeaderHandle = GetDlgItem(ListView1->Handle, 0);

for(int i=0;i < ListView1->Columns->Count; i++)
{
hdi.mask = HDI_TEXT | HDI_FORMAT | HDI_WIDTH;
hdi.fmt = HDF_LEFT | HDF_OWNERDRAW | HDF_STRING;
hdi.cxy = ListView1->Columns->Items[i]->Width;
hdi.cchTextMax = ListView1->Columns->Items[i]->Caption.Length();
hdi.pszText = ListView1->Columns->Items[i]->Caption.c_str();

Header_SetItem(HeaderHandle, i, &hdi);
}
}
3、编写代码:
void __fastcall TForm1::NewLVWndProc(TMessage& Message)
{
if(Message.Msg == WM_DRAWITEM)
{
DRAWITEMSTRUCT* dis;
TRect Rect;
TCanvas* FCanvas;
int LVOffset = 0;
AnsiString ColCaption;

///////////
dis = (DRAWITEMSTRUCT*)Message.LParam;

FCanvas = new TCanvas();
FCanvas->Handle = dis->hDC;
Rect = (TRect)dis->rcItem;

FCanvas->Brush->Color = ListView1->Color;
FCanvas->FillRect(Rect);

//Draw LV first
if(ListView1->SmallLVs != NULL && ListView1->Columns->Items[dis->itemID]->LVIndex != -1)
{
LVOffset = 16 + 12;
ListView1->SmallLVs->Draw(FCanvas,
Rect.Left + 6,
Rect.Top + 1,
ListView1->Columns->Items[dis->itemID]->LVIndex,
true);
}

// 采用和TListView相同的字体颜色
FCanvas->Font->Assign(ListView1->Font);
FCanvas->Font->Color = ListView1->Font->Color;
FCanvas->Brush->Style = bsClear;

ColCaption = ListView1->Columns->Items[dis->itemID]->DisplayName;

DrawTextEx(FCanvas->Handle,Str.c_str(),
ColCaption.Length(),
&TRect(Rect.Left + 5 + LVOffset,Rect.Top + 1,Rect.Right,Rect.Bottom),
DT_END_ELLIPSIS,NULL);

delete FCanvas;

Message.Result = 1;
return;
}
//把其它消息发送到原来的处理函数
OldLVWndProc(Message);
}
上面代码好像已经成功了,确切地说是只完成了一半,因为只要你改变了列的大小,它马上就恢复了原来的样子了。所以还有一步操作要做:
void __fastcall TForm1::NewLVWndProc(TMessage& Message)
{
if(Message.Msg == WM_DRAWITEM)
{
}
else if(Message.Msg == WM_PAINT)
{
if(this->ViewStyle == vsReport)
{
//先进行正常画
OldLVWndProc(Message);
//每一次画完之后都必须重新设置属性
SetupColumnToOwnerDraw(i);
//再画
OldLVWndProc(Message);
return;
}
}
//把其它消息发送到原来的处理函数
OldLVWndProc(Message);
}
1、首先,那个SysHeader32的每一个Item都必须具有HDF_OWNERDRAW属性。
2、当Item具有HDF_OWNERDRAW时,Windows在画它们之前将向SysHeader32的Owner(也就是TListView)发送WM_DRAWITEM消息,因此必须截获TListView的窗口过程检测消息WM_DRAWITEM然后自己画。
大概步骤如下:
1、定义变量和方法
TWndMethod OldLVWndProc; 
void __fastcall NewLVWndProc(TMessage& Message);2、在FormCreate中安装新的窗口过程
OldLVWndProc=LV1->WindowProc;
LV1->WindowProc=NewLVWndProc; 
//设置属性
SetupColumnToOwnerDraw(); 
//-------------------------------------------
void __fastcall SetupColumnToOwnerDraw()
{
HWND HeaderHandle;
HD_ITEM hdi; 
HeaderHandle = GetDlgItem(ListView1->Handle, 0); 
for(int i=0;i < ListView1->Columns->Count; i++)
{
hdi.mask = HDI_TEXT | HDI_FORMAT | HDI_WIDTH;
hdi.fmt = HDF_LEFT | HDF_OWNERDRAW | HDF_STRING;
hdi.cxy = ListView1->Columns->Items[i]->Width;
hdi.cchTextMax = ListView1->Columns->Items[i]->Caption.Length();
hdi.pszText = ListView1->Columns->Items[i]->Caption.c_str(); 
Header_SetItem(HeaderHandle, i, &hdi);
}
}3、编写代码:
void __fastcall TForm1::NewLVWndProc(TMessage& Message)
{
if(Message.Msg == WM_DRAWITEM)
{
DRAWITEMSTRUCT* dis;
TRect Rect;
TCanvas* FCanvas;
int LVOffset = 0;
AnsiString ColCaption; 
///////////
dis = (DRAWITEMSTRUCT*)Message.LParam; 
FCanvas = new TCanvas();
FCanvas->Handle = dis->hDC;
Rect = (TRect)dis->rcItem; 
FCanvas->Brush->Color = ListView1->Color;
FCanvas->FillRect(Rect); 
//Draw LV first
if(ListView1->SmallLVs != NULL && ListView1->Columns->Items[dis->itemID]->LVIndex != -1)
{
LVOffset = 16 + 12;
ListView1->SmallLVs->Draw(FCanvas,
Rect.Left + 6,
Rect.Top + 1,
ListView1->Columns->Items[dis->itemID]->LVIndex,
true);
} 
// 采用和TListView相同的字体颜色
FCanvas->Font->Assign(ListView1->Font);
FCanvas->Font->Color = ListView1->Font->Color;
FCanvas->Brush->Style = bsClear; 
ColCaption = ListView1->Columns->Items[dis->itemID]->DisplayName; 
DrawTextEx(FCanvas->Handle,Str.c_str(),
ColCaption.Length(),
&TRect(Rect.Left + 5 + LVOffset,Rect.Top + 1,Rect.Right,Rect.Bottom),
DT_END_ELLIPSIS,NULL); 
delete FCanvas; 
Message.Result = 1;
return;
}
//把其它消息发送到原来的处理函数
OldLVWndProc(Message);
}上面代码好像已经成功了,确切地说是只完成了一半,因为只要你改变了列的大小,它马上就恢复了原来的样子了。所以还有一步操作要做:
void __fastcall TForm1::NewLVWndProc(TMessage& Message)
{
if(Message.Msg == WM_DRAWITEM)
{
}
else if(Message.Msg == WM_PAINT)
{
if(this->ViewStyle == vsReport)
{
//先进行正常画
OldLVWndProc(Message);
//每一次画完之后都必须重新设置属性
SetupColumnToOwnerDraw(i);
//再画
OldLVWndProc(Message);
return;
}
}
//把其它消息发送到原来的处理函数
OldLVWndProc(Message);
}


浙公网安备 33010602011771号