您的位置:首页 > 编程语言 > Delphi

delphi listview自绘图形

2015-08-20 23:45 471 查看
自画TlistView带进度条的Item

TListView的Item条一般是由系统自画的,但电驴就实现了自画,使之看起来很漂亮,我们用DELPHI也可以实现!

 


 

首先要引用CommCtrl单元,这是TListView底层控制单元:

uses

 CommCtrl;

 

//画状态条

procedure DrawSubItem(LV: TListView; Item: TListItem; SubItem: Integer;

 Prosition: Single; Max, Style: Integer; IsShowProgress: Boolean;

 DrawColor: TColor = $00005B00;

 FrameColor: TColor = $00002F00);

//获取SubItem的区域

 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);

 

        //画一个外框

          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);

        //根据百分比算出要画的进度条内容宽度

          iWidth := R.Right - Round((R.Right - r.Left) * ((100 - Prosition) /

            100));

          case Style of

            0: //进度条类型,实心填充

              begin

                Canvas.Brush.Color := DrawColor;

                r.Right := iWidth;

                Canvas.FillRect(r);

              end;

            1: //进度条类型,竖线填充

              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;

//画好了进度条后,现在要做的就是显示进度数字了

          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;

//进度条全部画完,把颜色设置成默认色了

        Canvas.Brush.Color := Color;

 

      end

    end;

 except

 end;

end;

 

 

上面是画进度条的,现在要给TlistView处理Item重绘的消息,事件是OnCustomDrawItem,需要说明的是,如果想要随心所欲的自画Item,那么就要全部自己来完成,不再需要系统来处理:

procedure TForm1.ListView1CustomDrawItem(

 Sender: TCustomListView; Item: TListItem; State: TCustomDrawState;

 var DefaultDraw: Boolean);

var

 BoundRect, Rect: TRect;

 i: integer;

 TextFormat: Word;

 LV: TListView;

 

//这个子过程是用来画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;

    //开始画图标

    i := PDownLoadListItem(Item.Data)^.StatsImageIndex;

    if i > -1 then

    begin

    //获取图标的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);

 

//这个地方你可以根据自己的要求设置成想要的颜色,实现突出显示

 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

//先画选择框与图标

          Draw_CheckBox_ImageList(BoundRect, LV.Canvas, Item.Checked);

//再画Caption的文字

          InflateRect(Rect, -(5 + ImageList_Stats.Width), 0); //向后移3个像素,避免被后面画线框时覆盖

          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 //显示状态条

          begin

//开始处理进度条了,这个示例是第3栏显示进度条,可以自己随便定义

            DrawSubItem(TListView(Sender),

              item,

              i,

              StrToFloatDef(Item.SubItems[i - 1], 0),

              100,

              0,

              True,

 //这里用了一个Lable来选颜色,你自己可以使用一个变量来代替

             LableProgressColor.Color, //进度条外框颜色

              LableProgressColor.Color //进度条颜色

);

 

          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//控件是否处于激活状态

      LV.Canvas.Brush.Color := $00DAA07A // $00E2B598; //clHighlight;

    else

      LV.Canvas.Brush.Color := $00E2B598; //$00DAA07A // clHighlight;

    LV.Canvas.FrameRect(BoundRect); //

 end;

 

 DefaultDraw := False; //不让系统画了

 

 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';//设置为30%

//然后刷新这个item

ReDrawItem(ListView1.handle,Item.index);

 

不用进度条时的效果图:

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: