爱者家园电脑网络VC编程交流自画TlistView带进度条的Item(delphi)
    
 
自画TlistView带进度条的Item(delphi)
发起人:txiang  回复数:0  浏览数:11688  最后更新:2010/4/18 21:46:57 by txiang

选择查看 发表新帖 搜索更多相关主题  帖子排序:
2010/4/18 21:46:57
txiang





角  色:注册用户
发 帖 数:31
经 验 值:62
注册时间:2007/8/6
自画TlistView带进度条的Item(delphi)

自画TlistView带进度条的Item - [学习资料]

<div class=postBody>

版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://proc.blogbus.com/logs/28162911.html

<div style="TEXT-INDENT: 21.75pt">TListView的Item条一般是由系统自画的,但电驴就实现了自画,使之看起来很漂亮,我们用DELPHI也可以实现!</div><div style="TEXT-INDENT: 21.75pt"></div><div style="TEXT-INDENT: 21.75pt">首先要引用CommCtrl单元,这是TListView底层控制单元:</div><div align=left>uses</div><div align=left> CommCtrl;</div><div align=left>//画状态条</div><div align=left>procedure DrawSubItem(LV: TListView; Item: TListItem; SubItem: Integer;</div><div align=left> Prosition: Single; Max, Style: Integer; IsShowProgress: Boolean;</div><div align=left> DrawColor: TColor = $00005B00;</div><div align=left> FrameColor: TColor = $00002F00);</div><div align=left>//获取SubItem的区域</div><div align=left> function GetItemRect(LV_Handle, iItem, iSubItem: Integer): TRect;</div><div align=left> var</div><div align=left>    Rect: TRect;</div><div align=left> begin</div><div align=left>    ListView_GetSubItemRect(LV_Handle, iItem, iSubItem, LVIR_LABEL, @Rect);</div><div align=left>    Result := Rect;</div><div align=left> end;</div><div align=left>var</div><div align=left> PaintRect, r: TRect;</div><div align=left> i, iWidth, x, y: integer;</div><div align=left> S: string;</div><div align=left>begin</div><div align=left> try</div><div align=left></div><div align=left>    with lv do</div><div align=left>    begin</div><div align=left>      //LockPaint := True;</div><div align=left>      PaintRect := GetItemRect(LV.Handle, Item.Index, SubItem);</div><div align=left>     r := PaintRect;</div><div align=left>//      if SubItem = DrawSubItem then</div><div align=left>      Begin</div><div align=left>        //这一段是算出百分比</div><div align=left>        if Prosition >= Max then</div><div align=left>          Prosition := 100</div><div align=left>        else</div><div align=left>          if Prosition <= 0 then</div><div align=left>            Prosition := 0</div><div align=left>          else</div><div align=left>            Prosition := Round((Prosition / Max) * 100);</div><div align=left>        if (Prosition = 0) and (not IsShowProgress) then</div><div align=left>        begin </div><div align=left>        //如果是百分比是0,就直接显示空白</div><div align=left>          Canvas.FillRect(r);</div><div align=left>        end</div><div align=left>        else</div><div align=left>        begin</div><div align=left>        //先直充背景色</div><div align=left>          Canvas.FillRect(r);</div><div align=left>          Canvas.Brush.Color := Color;</div><div align=left>//          Canvas.FillRect(r);</div><div align=left>        //画一个外框</div><div align=left>          InflateRect(r, -2, -2);</div><div align=left>          Canvas.Brush.Color := FrameColor; //$00002F00;</div><div align=left>          Canvas.FrameRect(R);</div><div align=left>          Canvas.Brush.Color := Color;</div><div align=left>          InflateRect(r, -1, -1);</div><div align=left>//          Canvas.FillRect(r);</div><div align=left>          InflateRect(r, -1, -1);</div><div align=left>        //根据百分比算出要画的进度条内容宽度</div><div align=left>          iWidth := R.Right - Round((R.Right - r.Left) * ((100 - Prosition) /</div><div align=left>            100));</div><div align=left>          case Style of</div><div align=left>            0: //进度条类型,实心填充</div><div align=left>              begin</div><div align=left>                Canvas.Brush.Color := DrawColor;</div><div align=left>                r.Right := iWidth;</div><div align=left>                Canvas.FillRect(r);</div><div align=left>              end;</div><div align=left>            1: //进度条类型,竖线填充</div><div align=left>              begin</div><div align=left>                i := r.Left;</div><div align=left>                while i < iWidth do</div><div align=left>                begin</div><div align=left>                  Canvas.Pen.Color := Color;</div><div align=left>                  Canvas.MoveTo(i, r.Top);</div><div align=left>                  Canvas.Pen.Color := DrawColor;</div><div align=left>                  canvas.LineTo(i, r.Bottom);</div><div align=left>                  Inc(i, 3);</div><div align=left>                end;</div><div align=left>              end;</div><div align=left>          end;</div><div style="TEXT-INDENT: 45pt" align=left>//画好了进度条后,现在要做的就是显示进度数字了</div><div align=left>          Canvas.Brush.Style := bsClear;</div><div align=left>          if Prosition = Round(Prosition) then</div><div align=left>            S := Format('%d%%', [Round(Prosition)])</div><div align=left>          else</div><div align=left>            S := FormatFloat('#0.0', Prosition);</div><div align=left>          with PaintRect do</div><div align=left>          begin</div><div align=left>            x := Left + (Right - Left + 1 - Canvas.TextWidth(S)) div 2;</div><div align=left>            y := Top + (Bottom - Top + 1 - Canvas.TextHeight(S)) div 2;</div><div align=left>          end;</div><div align=left>          SetBkMode(Canvas.handle, TRANSPARENT);</div><div align=left>          Canvas.TextRect(PaintRect, x, y, S);</div><div align=left>        end;</div><div style="TEXT-INDENT: 36pt" align=left>//进度条全部画完,把颜色设置成默认色了</div><div align=left>        Canvas.Brush.Color := Color;</div><div align=left>      end</div><div align=left>    end;</div><div align=left> except</div><div align=left> end;</div><div align=left>end;</div><div align=left>上面是画进度条的,现在要给TlistView处理Item重绘的消息,事件是OnCustomDrawItem需要说明的是,如果想要随心所欲的自画Item,那么就要全部自己来完成,不再需要系统来处理:</div><div align=left>procedure TForm1.ListView1CustomDrawItem(</div><div align=left> Sender: TCustomListView; Item: TListItem; State: TCustomDrawState;</div><div align=left> var DefaultDraw: Boolean);</div><div align=left>var</div><div align=left> BoundRect, Rect: TRect;</div><div align=left> i: integer;</div><div align=left> TextFormat: Word;</div><div align=left> LV: TListView;</div><div align=left>//这个子过程是用来画CheckBoxImageList</div><div align=left> procedure Draw_CheckBox_ImageList(r: TRect; aCanvas: TCanvas; Checked: Boolean);</div><div align=left> var</div><div align=left>    R1: TRect;</div><div align=left>    i: integer;</div><div align=left> begin</div><div align=left>    if Sender.Checkboxes then</div><div align=left>    begin</div><div align=left>      aCanvas.Pen.Color := clBlack;</div><div align=left>      aCanvas.Pen.Width := 2;</div><div align=left>      //CheckBox外框</div><div align=left>      aCanvas.Rectangle(r.Left + 2, r.Top + 2, r.Left + 14, r.Bottom - 2);</div><div align=left>      if Checked then</div><div align=left>      begin //CheckBox的勾</div><div align=left>        aCanvas.MoveTo(r.Left + 4, r.Top + 6);</div><div align=left>        aCanvas.LineTo(r.Left + 6, r.Top + 11);</div><div align=left>        aCanvas.LineTo(r.Left + 11, r.Top + 5);</div><div align=left>      end;</div><div align=left>      aCanvas.Pen.Width := 1;</div><div align=left>    end;</div><div align=left>    //开始画图标</div><div align=left>    i := PDownLoadListItem(Item.Data)^.StatsImageIndex;</div><div align=left>    if i > -1 then</div><div align=left>    begin</div><div align=left>    //获取图标的RECT</div><div align=left>      if Boolean(ListView_GetSubItemRect(sender.Handle, item.Index, 0, LVIR_ICON, @R1)) then</div><div align=left>      begin</div><div align=left>        ImageList_Stats.Draw(LV.Canvas, R1.Left, R1.Top, i);</div><div align=left>        if item.ImageIndex > -1 then</div><div align=left>          LV.SmallImages.Draw(LV.Canvas, R1.Right + 2, R1.Top, item.ImageIndex);</div><div align=left>      end;</div><div align=left>    end;</div><div align=left> end;</div><div align=left>begin</div><div align=left> LV := ListView1;</div><div align=left> BoundRect := Item.DisplayRect(drBounds);</div><div align=left> InflateRect(BoundRect, -1, 0);</div><div align=left>//这个地方你可以根据自己的要求设置成想要的颜色,实现突出显示</div><div align=left> LV.Canvas.Font.Color := clBtnText;</div><div align=left>//查看是否是被选中</div><div align=left> if Item.Selected then</div><div align=left> begin</div><div align=left>    if cdsFocused in State then</div><div align=left>    begin</div><div align=left>      LV.Canvas.Brush.Color := $00ECCCB9; // //clHighlight;</div><div align=left>    end</div><div align=left>    else</div><div align=left>    begin</div><div align=left>      LV.Canvas.Brush.Color := $00F8ECE5; //clSilver;</div><div align=left>    end;</div><div align=left> end</div><div align=left> else</div><div align=left> begin</div><div align=left>    if (Item.Index mod 2) = 0 then</div><div align=left>      LV.Canvas.Brush.Color := clWhite</div><div align=left>    else</div><div align=left>      LV.Canvas.Brush.Color := $00F2F2F2;</div><div align=left> end;</div><div align=left> LV.Canvas.FillRect(BoundRect); //初始化背景</div><div align=left> for i := 0 to LV.Columns.Count - 1 do</div><div align=left> begin</div><div align=left> //获取SubItemRect</div><div align=left>    ListView_GetSubItemRect(LV.Handle, Item.Index, i, LVIR_LABEL, @Rect);</div><div align=left>    case LV.Columns.Alignment of</div><div align=left>      taLeftJustify:</div><div align=left>        TextFormat := 0;</div><div align=left>      taRightJustify:</div><div align=left>        TextFormat := DT_RIGHT;</div><div align=left>      taCenter:</div><div align=left>        TextFormat := DT_CENTER;</div><div align=left>    end;</div><div align=left>    case i of</div><div align=left>      0: //Caption0就是表示Caption,这不是Subitems[0]</div><div align=left>        begin</div><div style="TEXT-INDENT: 45pt" align=left>//先画选择框与图标</div><div align=left>          Draw_CheckBox_ImageList(BoundRect, LV.Canvas, Item.Checked);</div><div style="TEXT-INDENT: 45pt" align=left>//再画Caption的文字</div><div align=left>          InflateRect(Rect, -(5 + ImageList_Stats.Width), 0); //向后移3个像素,避免被后面画线框时覆盖</div><div align=left>          DrawText(</div><div align=left>            LV.Canvas.Handle,</div><div align=left>            PCHAR(Item.Caption),</div><div align=left>            Length(Item.Caption),</div><div align=left>            Rect,</div><div align=left>            DT_VCENTER or DT_SINGLELINE or DT_END_ELLIPSIS or TextFormat);</div><div align=left>        end;</div><div align=left>      1..MaxInt: //Subitems</div><div align=left>        begin</div><div align=left>          if i - 1 = 2 then //显示状态条</div><div align=left>          begin</div><div style="TEXT-INDENT: 45pt" align=left>//开始处理进度条了,这个示例是第3栏显示进度条,可以自己随便定义</div><div align=left>            DrawSubItem(TListView(Sender),</div><div align=left>              item,</div><div align=left>              i,</div><div align=left>              StrToFloatDef(Item.SubItems[i - 1], 0),</div><div align=left>              100,</div><div align=left>              0,</div><div align=left>              True,</div><div style="TEXT-INDENT: 45pt" align=left> //这里用了一个Lable来选颜色,你自己可以使用一个变量来代替</div><div align=left>             LableProgressColor.Color, //进度条外框颜色</div><div align=left>              LableProgressColor.Color //进度条颜色</div><div style="TEXT-INDENT: 63pt" align=left>);</div><div align=left>          end</div><div align=left>          else</div><div style="TEXT-INDENT: 45pt" align=left>//SubItem的文字</div><div align=left>            if i - 1 <= Item.SubItems.Count - 1 then</div><div align=left>              DrawText(</div><div align=left>                LV.Canvas.Handle,</div><div align=left>                PCHAR(Item.SubItems[i - 1]),</div><div align=left>                Length(Item.SubItems[i - 1]),</div><div align=left>                Rect,</div><div align=left>                DT_VCENTER or DT_SINGLELINE or DT_END_ELLIPSIS or TextFormat);</div><div align=left>        end;</div><div align=left>    end;</div><div align=left> end;</div><div align=left> LV.Canvas.Brush.Color := clWhite;</div><div align=left> if Item.Selected then //画选中条外框</div><div align=left> begin</div><div align=left>    if cdsFocused in State then//控件是否处于激活状态</div><div align=left>      LV.Canvas.Brush.Color := $00DAA07A // $00E2B598; //clHighlight;</div><div align=left>    else</div><div align=left>      LV.Canvas.Brush.Color := $00E2B598; //$00DAA07A // clHighlight;</div><div align=left>    LV.Canvas.FrameRect(BoundRect); // </div><div align=left> end;</div><div align=left> DefaultDraw := False; //不让系统画了</div><div align=left> with Sender.Canvas do</div><div align=left>    if Assigned(Font.OnChange) then Font.OnChange(Font);</div><div align=left>end;</div><div align=left></div><div align=left>function ReDrawItem(HwndLV: HWND; ItemIndex: integer): boolean;
begin
  Result := ListView_RedrawItems(HwndLV, ItemIndex, ItemIndex);
end;
</div><div align=left></div><div align=left>//使用:</div><div align=left>item:=ListView1.Selected;</div><div align=left>item.subitems[1]:='30';//设置为30%</div><div align=left>//然后刷新这个item
ReDrawItem(ListView1.handle,Item.index);
<div style="TEXT-INDENT: 21.75pt">不用进度条时的效果图:</div><div style="TEXT-INDENT: 21.75pt" align=center></div></div></div>


  • 联系我们 - sieye - 论坛存档 - 返回顶部
    Powered by BBSXP 2008 SP2 ACCESS © 1998-2024 Yuzi.Net
  • Processed in 0.06 second(s)
    Server Time 2024/11/27 3:54:22