版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://proc.blogbus.com/logs/28162911.html
</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>//这个子过程是用来画CheckBox和ImageList的</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> //获取SubItem的Rect</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: //画Caption,0就是表示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;
</div></div></div>