0

在更改列表视图的子项的文本时,我需要刷并填充一整行:

procedure TForm1.ListViewDrawItem(Sender: TCustomListView;
  Item: TListItem; Rect: TRect; State: TOwnerDrawState);
begin
  if Item.SubItems[2]='Done'
   then
  begin
    Sender.Canvas.Font.Color := clBlack;
    Sender.Canvas.Brush.Color := clGreen;
    Sender.Canvas.Brush.Style := bsSolid;
    Sender.Canvas.FillRect(Rect);
  end;
end;

但是 Sender.Canvas。FillRect(Rect)将仅填充 SubItem 的 Rect。如何填满一整行?

这个问题是在Delphi 的基础上提出的:how to draw small icons in List View on CustomDrawItem

谢谢!

4

1 回答 1

5

首先,如果您有三列,它们是CaptionSubItems[0]SubItems[1],还记得吗?没有SubItems[2]

无论如何,这很容易。您只需要对旧代码进行非常非常小的修改。

procedure TForm1.ListView1DrawItem(Sender: TCustomListView; Item: TListItem;
  Rect: TRect; State: TOwnerDrawState);
var
  i: Integer;
  x1, x2: integer;
  r: TRect;
  S: string;
const
  DT_ALIGN: array[TAlignment] of integer = (DT_LEFT, DT_RIGHT, DT_CENTER);
begin
  if SameText(Item.SubItems[1], 'done') then
  begin
    Sender.Canvas.Font.Color := clBlack;
    Sender.Canvas.Brush.Color := clLime;
  end
  else
    if Odd(Item.Index) then
    begin
      Sender.Canvas.Font.Color := clBlack;
      Sender.Canvas.Brush.Color := $F6F6F6;
    end
    else
    begin
      Sender.Canvas.Font.Color := clBlack;
      Sender.Canvas.Brush.Color := clWhite;
    end;
  Sender.Canvas.Brush.Style := bsSolid;
  Sender.Canvas.FillRect(Rect);
  x1 := 0;
  x2 := 0;
  r := Rect;
  Sender.Canvas.Brush.Style := bsClear;
  Sender.Canvas.Draw(3, r.Top + (r.Bottom - r.Top - bm.Height) div 2, bm);
  for i := 0 to ListView1.Columns.Count - 1 do
  begin
    inc(x2, ListView1.Columns[i].Width);
    r.Left := x1;
    r.Right := x2;
    if i = 0 then
    begin
      S := Item.Caption;
      r.Left := bm.Width + 6;
    end
    else
      S := Item.SubItems[i - 1];
    DrawText(Sender.Canvas.Handle,
      S,
      length(S),
      r,
      DT_SINGLELINE or DT_ALIGN[ListView1.Columns[i].Alignment] or
        DT_VCENTER or DT_END_ELLIPSIS);
    x1 := x2;
  end;
end;

截屏

特别注意我使用clLime而不是clGreen,因为背景clBlack上的文字clGreen看起来很糟糕!不过,您可能会考虑背景clWhite上的文字clGreen

截屏

更新以回应评论:

要更改列表视图的第三列,不能只做

procedure TForm1.FormClick(Sender: TObject);
begin
  ListView1.Items[3].SubItems[1] := 'Done';
end;

确实,Windows 不知道一列的数据会影响整行的外观!最简单的解决方法是告诉 Windows 在您更改值时重新绘制整个控件更好:只需告诉 Windows 重绘当前行:

procedure TForm1.FormClick(Sender: TObject);
begin
  ListView1.Items[3].SubItems[1] := 'Done';
  ListView1.Items[3].Update;
end;
于 2011-07-07T21:00:41.197 回答