Delphi的ListView控件提供了一个叫OnCustomDrawSubItem的event给developer去对SubItem的颜色或者其它进行自定义。
event OnCustomDrawSubItem的定义如下:
procedure TForm1.ListView1CustomDrawSubItem(Sender: TCustomListView;
Item: TListItem; SubItem: Integer; State: TCustomDrawState;var DefaultDraw: Boolean);
参数说明如下:
Item: TListItem,正在被draw的item对象;
SubItem:integer,正在被draw的subitem的索引;
以下以设置subitem的颜色为例。
可以通过设置ListView的Canvas的颜色来改变subitem的颜色:
procedure TForm1.ListView1CustomDrawSubItem(Sender: TCustomListView;
Item: TListItem; SubItem: Integer; State: TCustomDrawState;var DefaultDraw: Boolean);
begin
ListView1.Canvas.Font.Color := clRed; // Set the subitem color as red.
end;
如上,listview的每个subitem都会被draw成红色,但是实际效果却不是我们想象的那样,每个subitem都是红色,如下:
第一列没有被draw成红色。
通过debug可以发现,subitem的值是从1开始的,第一个column是不能触发这个event,或者说这个event并不会处理第一个column,所以它叫CustomDrawSubItem。
同时还有一个比较特殊的,通过判断subitem的值,可以实现如下的效果:
实现代码如下
procedure TForm1.ListView1CustomDrawSubItem(Sender: TCustomListView;
Item: TListItem; SubItem: Integer; State: TCustomDrawState;var DefaultDraw: Boolean);
begin
if subitem = 1 thenListView1.Canvas.Font.Color := clBlue; // From subitem 1, draw blue.
if subitem = 2 thenListView1.Canvas.Font.Color := clRed; // From subitem 2, draw red.
if subitem = 3 thenListView1.Canvas.Font.Color := clGreen; // From subitem 3, draw green.
if subitem = 4 thenListView1.Canvas.Font.Color := clYellow; // From subitem 4, draw yellow.
end;
ListView是通过Canvas来做draw动作的,我加上这段逻辑,对Canvas的前景色进行更改:
从第二个column(subitem 1)开始,Canvas的前景色为blue,如果没有之后的逻辑,subitem 1之后的subitem都会用这个前景色来做draw的动作,也就是说,如果没有if subitem = 2, subitem = 3, subitem = 4这些逻辑的话,subitem后的所有subitem都会是blue。
同理,使用blue色draw完subitem 1后,在draw subitem 2时,将Canvas的前景色改成了red,所以subitem 2会是red。
同理,subitem 3会是green,subitem 4会是yellow。
但是,尽管如此,我们还是没有办法将第一个column的颜色进行改变。
确实,在OnCustomDrawSubItem中是做不到这一点的,需要另外一个event的辅助,那就是OnCustomDrawItem,这个event是用来draw整个item的,
当然也会把第一个column的进行定制。
试想一下,如果我们在OnCustomDrawItem中把整个item都设成紫色,然后在OnCustomDrawItem中把subitem设置成其它的颜色,那不就是所有的column都有颜色了吗。
通过测试,也能证明每次都是执行一个Item的OnCustomDrawItem后,再对这个item的每个subitem执行OnCustomDrawSubItem,所以不存在时序的问题。
procedure TForm1.ListView1CustomDrawSubItem(Sender: TCustomListView;
Item: TListItem; SubItem: Integer; State: TCustomDrawState;var DefaultDraw: Boolean);
begin
// Log when OnCustomDrawSubItem called.
with ListView2.Items.Add do beginCaption := 'Draw SubItem';end;
// Set the color of subitems only the item's caption is "A"
if item.Caption <> 'A' thenExit;if subitem = 1 thenListView1.Canvas.Font.Color := clBlue;if subitem = 2 thenListView1.Canvas.Font.Color := clRed;if subitem = 3 thenListView1.Canvas.Font.Color := clGreen;if subitem = 4 thenListView1.Canvas.Font.Color := clYellow;end;
procedure TForm1.ListView1CustomDrawItem(Sender: TCustomListView;
Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
// Log when OnCustomDrawItem called.
with ListView2.Items.Add do beginCaption := 'Draw Item';end;
if item.Caption = 'A' then // Set the item's color only the item's caption is "A".ListView1.Canvas.Font.Color := clPurple;end;
运行效果如下:
完整源码:
PAS
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, ComCtrls;type
TForm1 = class(TForm)ListView1: TListView;ListView2: TListView;procedure FormShow(Sender: TObject);
procedure ListView1CustomDrawSubItem(Sender: TCustomListView;
Item: TListItem; SubItem: Integer; State: TCustomDrawState;var DefaultDraw: Boolean);
procedure ListView1CustomDrawItem(Sender: TCustomListView;
Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
private{ Private declarations }public{ Public declarations }end;
var
Form1: TForm1;implementation
{$R *.dfm}procedure TForm1.FormShow(Sender: TObject);
var
lvItem: TListItem;lvCol: TListColumn;begin
with listView1 do beginwith Columns.Add do beginCaption := 'Col0';end;
with Columns.Add do beginCaption := 'Col1';end;
with Columns.Add do beginCaption := 'Col2';end;
with Columns.Add do beginCaption := 'Col3';end;
with Columns.Add do beginCaption := 'Col4';end;
end;
with listview1 do beginViewStyle:=vsreport;with Items.Add do beginCaption := 'A';SubItems.Add('A1');SubItems.Add('A2');SubItems.Add('A3');SubItems.Add('A4');end;
with Items.Add do beginCaption := 'B';SubItems.Add('B1');SubItems.Add('B2');SubItems.Add('B3');SubItems.Add('B4');end;
with Items.Add do beginCaption := 'C';SubItems.Add('C1');SubItems.Add('C2');SubItems.Add('C3');SubItems.Add('C4');end;
end;
end;
procedure TForm1.ListView1CustomDrawSubItem(Sender: TCustomListView;
Item: TListItem; SubItem: Integer; State: TCustomDrawState;var DefaultDraw: Boolean);
begin
//
if item.Caption <> 'A' thenExit;with ListView2.Items.Add do beginCaption := 'Draw SubItem';end;
if subitem = 1 thenListView1.Canvas.Font.Color := clBlue;if subitem = 2 thenListView1.Canvas.Font.Color := clRed;if subitem = 3 thenListView1.Canvas.Font.Color := clGreen;if subitem = 4 thenListView1.Canvas.Font.Color := clYellow;end;
procedure TForm1.ListView1CustomDrawItem(Sender: TCustomListView;
Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
//
with ListView2.Items.Add do beginCaption := 'Draw Item';end;
if item.Caption = 'A' thenListView1.Canvas.Font.Color := clPurple;end;
end.
DFM
object Form1: TForm1
Left = 356Top = 241Width = 608Height = 291Caption = 'Form1'Color = clBtnFaceFont.Charset = DEFAULT_CHARSETFont.Color = clWindowTextFont.Height = -11Font.Name = 'MS Sans Serif'Font.Style = []OldCreateOrder = FalseOnShow = FormShowPixelsPerInch = 96TextHeight = 13object ListView1: TListView
Left = 10Top = 10Width = 375Height = 215Columns = <>TabOrder = 0OnCustomDrawItem = ListView1CustomDrawItemOnCustomDrawSubItem = ListView1CustomDrawSubItemend
object ListView2: TListView
Left = 456Top = 16Width = 121Height = 209Columns = <itemend>
TabOrder = 1ViewStyle = vsReportend
end