自畫TlistView帶進(jìn)度條的Item
TListView的Item條一般是由系統(tǒng)自畫的,但電驢就實(shí)現(xiàn)了自畫,使之看起來(lái)很漂亮,我們用DELPHI也可以實(shí)現(xiàn)!
首先要引用CommCtrl單元,這是TListView底層控制單元:
uses
CommCtrl;
//畫狀態(tài)條
procedure DrawSubItem(LV: TListView; Item: TListItem; SubItem: Integer;
Prosition: Single; Max, Style: Integer; IsShowProgress: Boolean;
DrawColor: TColor = $00005B00;
FrameColor: TColor = $00002F00);
//獲取SubItem的區(qū)域
function GetItemRect(LV_Handle, iItem, iSubItem: Integer): TRect;
var
Rect: TRect;
begin
ListView_GetSubItemRect(LV_Handle, iItem, iSubItem, LVIR_LABEL, @Rect);
Result := Rect;
end;
var
PaintRect, r: TRect;
i, iWidth, x, y: integer;
S: string;
begin
try
with lv do
begin
//LockPaint := True;
PaintRect := GetItemRect(LV.Handle, Item.Index, SubItem);
r := PaintRect;
// if SubItem = DrawSubItem then
Begin
//這一段是算出百分比
if Prosition >= Max then
Prosition := 100
else
if Prosition <= 0 then
Prosition := 0
else
Prosition := Round((Prosition / Max) * 100);
if (Prosition = 0) and (not IsShowProgress) then
begin
//如果是百分比是0,就直接顯示空白
Canvas.FillRect(r);
end
else
begin
//先直充背景色
Canvas.FillRect(r);
Canvas.Brush.Color := Color;
// Canvas.FillRect(r);
//畫一個(gè)外框
InflateRect(r, -2, -2);
Canvas.Brush.Color := FrameColor; //$00002F00;
Canvas.FrameRect(R);
Canvas.Brush.Color := Color;
InflateRect(r, -1, -1);
// Canvas.FillRect(r);
InflateRect(r, -1, -1);
//根據(jù)百分比算出要畫的進(jìn)度條內(nèi)容寬度
iWidth := R.Right - Round((R.Right - r.Left) * ((100 - Prosition) /
100));
case Style of
0: //進(jìn)度條類型,實(shí)心填充
begin
Canvas.Brush.Color := DrawColor;
r.Right := iWidth;
Canvas.FillRect(r);
end;
1: //進(jìn)度條類型,豎線填充
begin
i := r.Left;
while i < iWidth do
begin
Canvas.Pen.Color := Color;
Canvas.MoveTo(i, r.Top);
Canvas.Pen.Color := DrawColor;
canvas.LineTo(i, r.Bottom);
Inc(i, 3);
end;
end;
end;
//畫好了進(jìn)度條后,現(xiàn)在要做的就是顯示進(jìn)度數(shù)字了
Canvas.Brush.Style := bsClear;
if Prosition = Round(Prosition) then
S := Format('%d%%', [Round(Prosition)])
else
S := FormatFloat('#0.0', Prosition);
with PaintRect do
begin
x := Left + (Right - Left + 1 - Canvas.TextWidth(S)) div 2;
y := Top + (Bottom - Top + 1 - Canvas.TextHeight(S)) div 2;
end;
SetBkMode(Canvas.handle, TRANSPARENT);
Canvas.TextRect(PaintRect, x, y, S);
end;
//進(jìn)度條全部畫完,把顏色設(shè)置成默認(rèn)色了
Canvas.Brush.Color := Color;
end
end;
except
end;
end;
上面是畫進(jìn)度條的,現(xiàn)在要給TlistView處理Item重繪的消息,事件是OnCustomDrawItem,需要說(shuō)明的是,如果想要隨心所欲的自畫Item,那么就要全部自己來(lái)完成,不再需要系統(tǒng)來(lái)處理:
procedure TForm1.ListView1CustomDrawItem(
Sender: TCustomListView; Item: TListItem; State: TCustomDrawState;
var DefaultDraw: Boolean);
var
BoundRect, Rect: TRect;
i: integer;
TextFormat: Word;
LV: TListView;
//這個(gè)子過(guò)程是用來(lái)畫CheckBox和ImageList的
procedure Draw_CheckBox_ImageList(r: TRect; aCanvas: TCanvas; Checked: Boolean);
var
R1: TRect;
i: integer;
begin
if Sender.Checkboxes then
begin
aCanvas.Pen.Color := clBlack;
aCanvas.Pen.Width := 2;
//畫CheckBox外框
aCanvas.Rectangle(r.Left + 2, r.Top + 2, r.Left + 14, r.Bottom - 2);
if Checked then
begin //畫CheckBox的勾
aCanvas.MoveTo(r.Left + 4, r.Top + 6);
aCanvas.LineTo(r.Left + 6, r.Top + 11);
aCanvas.LineTo(r.Left + 11, r.Top + 5);
end;
aCanvas.Pen.Width := 1;
end;
//開始畫圖標(biāo)
i := PDownLoadListItem(Item.Data)^.StatsImageIndex;
if i > -1 then
begin
//獲取圖標(biāo)的RECT
if Boolean(ListView_GetSubItemRect(sender.Handle, item.Index, 0, LVIR_ICON, @R1)) then
begin
ImageList_Stats.Draw(LV.Canvas, R1.Left, R1.Top, i);
if item.ImageIndex > -1 then
LV.SmallImages.Draw(LV.Canvas, R1.Right + 2, R1.Top, item.ImageIndex);
end;
end;
end;
begin
LV := ListView1;
BoundRect := Item.DisplayRect(drBounds);
InflateRect(BoundRect, -1, 0);
//這個(gè)地方你可以根據(jù)自己的要求設(shè)置成想要的顏色,實(shí)現(xiàn)突出顯示
LV.Canvas.Font.Color := clBtnText;
//查看是否是被選中
if Item.Selected then
begin
if cdsFocused in State then
begin
LV.Canvas.Brush.Color := $00ECCCB9; // //clHighlight;
end
else
begin
LV.Canvas.Brush.Color := $00F8ECE5; //clSilver;
end;
end
else
begin
if (Item.Index mod 2) = 0 then
LV.Canvas.Brush.Color := clWhite
else
LV.Canvas.Brush.Color := $00F2F2F2;
end;
LV.Canvas.FillRect(BoundRect); //初始化背景
for i := 0 to LV.Columns.Count - 1 do
begin
//獲取SubItem的Rect
ListView_GetSubItemRect(LV.Handle, Item.Index, i, LVIR_LABEL, @Rect);
case LV.Columns[i].Alignment of
taLeftJustify:
TextFormat := 0;
taRightJustify:
TextFormat := DT_RIGHT;
taCenter:
TextFormat := DT_CENTER;
end;
case i of
0: //畫Caption,0就是表示Caption,這不是Subitems[0]
begin
//先畫選擇框與圖標(biāo)
Draw_CheckBox_ImageList(BoundRect, LV.Canvas, Item.Checked);
//再畫Caption的文字
InflateRect(Rect, -(5 + ImageList_Stats.Width), 0); //向后移3個(gè)像素,避免被后面畫線框時(shí)覆蓋
DrawText(
LV.Canvas.Handle,
PCHAR(Item.Caption),
Length(Item.Caption),
Rect,
DT_VCENTER or DT_SINGLELINE or DT_END_ELLIPSIS or TextFormat);
end;
1..MaxInt: //畫Subitems[i]
begin
if i - 1 = 2 then //顯示狀態(tài)條
begin
//開始處理進(jìn)度條了,這個(gè)示例是第3欄顯示進(jìn)度條,可以自己隨便定義
DrawSubItem(TListView(Sender),
item,
i,
StrToFloatDef(Item.SubItems[i - 1], 0),
100,
0,
True,
//這里用了一個(gè)Lable來(lái)選顏色,你自己可以使用一個(gè)變量來(lái)代替
LableProgressColor.Color, //進(jìn)度條外框顏色
LableProgressColor.Color //進(jìn)度條顏色
);
end
else
//畫SubItem的文字
if i - 1 <= Item.SubItems.Count - 1 then
DrawText(
LV.Canvas.Handle,
PCHAR(Item.SubItems[i - 1]),
Length(Item.SubItems[i - 1]),
Rect,
DT_VCENTER or DT_SINGLELINE or DT_END_ELLIPSIS or TextFormat);
end;
end;
end;
LV.Canvas.Brush.Color := clWhite;
if Item.Selected then //畫選中條外框
begin
if cdsFocused in State then//控件是否處于激活狀態(tài)
LV.Canvas.Brush.Color := $00DAA07A // $00E2B598; //clHighlight;
else
LV.Canvas.Brush.Color := $00E2B598; //$00DAA07A // clHighlight;
LV.Canvas.FrameRect(BoundRect); //
end;
DefaultDraw := False; //不讓系統(tǒng)畫了
with Sender.Canvas do
if Assigned(Font.OnChange) then Font.OnChange(Font);
end;
function ReDrawItem(HwndLV: HWND; ItemIndex: integer): boolean;
begin
Result := ListView_RedrawItems(HwndLV, ItemIndex, ItemIndex);
end;
//使用:
item:=ListView1.Selected;
item.subitems[1]:='30';//設(shè)置為30%
//然后刷新這個(gè)item
ReDrawItem(ListView1.handle,Item.index);
不用進(jìn)度條時(shí)的效果圖: