为什么ListView会忽略自定义绘图中的字体和画笔设置?

Why does ListView ignores font and brush settings in custom drawing?

我正在尝试使用自定义字体样式和背景颜色在列表视图中绘制项目。表单上有一个默认的列表视图。我已将 ViewStyle 更改为 vsReport,将 OwnerDraw 更改为 True。添加了 3 列和 3 个项目。并分配 OnCustomDrawItem 事件:

procedure TForm1.lv1CustomDrawItem(Sender: TCustomListView; Item: TListItem;
  State: TCustomDrawState; var DefaultDraw: Boolean);
var
  lvCanvas: TCanvas;
  R: TRect;
  S: string;
begin
  DefaultDraw := False;

  lvCanvas := Sender.Canvas;

  // column 1
  R := Item.DisplayRect(drBounds);
  R.Right := Sender.Column[0].Width;

  lvCanvas.Brush.Color := clRed;
  lvCanvas.Font.Style := [fsBold];
  S := 'Bold with red background';

  lvCanvas.FillRect(R);
  lvCanvas.TextRect(R, S, [tfSingleLine, tfEndEllipsis, tfCenter, tfVerticalCenter]);

  // column 2
  R.Left := R.Right;
  R.Right := R.Left + Sender.Column[1].Width;

  lvCanvas.Brush.Color := clGreen;
  lvCanvas.Font.Style := [fsItalic];
  S := 'Italic with green background';

  lvCanvas.FillRect(R);
  lvCanvas.TextRect(R, S, [tfSingleLine, tfEndEllipsis, tfCenter, tfVerticalCenter]);

  // column 3
  R.Left := R.Right;
  R.Right := R.Left + Sender.Column[2].Width;

  lvCanvas.Brush.Color := clBlue;
  lvCanvas.Font.Style := [fsUnderline];
  S := 'Underline with blue background';

  lvCanvas.FillRect(R);
  lvCanvas.TextRect(R, S, [tfSingleLine, tfEndEllipsis, tfCenter, tfVerticalCenter]);
end;

但结果不如预期:

第二列中的文本应为斜体,但不应为粗体且背景为绿色。 第三列中的文本应加下划线,但不能是粗体和蓝色背景。

谁能给我解释一下这是怎么回事?

我也试过了,确实不行。 canvas 不做你想做的事。所以我尝试使用 自己的控件 canvas,希望它能做得更好,而且确实如此。 (稍后我可能会 post 拍张照片)。

试试下面的代码:

var
  lvCanvas: TCanvas;
  R: TRect;
  S: string;
begin
  DefaultDraw := False;

  lvCanvas := TControlCanvas.Create;

  { Try-finally-end is needed, because this Canvas is under our control. }
  try
    TControlCanvas(lvCanvas).Control := lv1;

    { ... Start of original drawing code ... }
    // column 1
    R := Item.DisplayRect(drBounds);

    { ... Drawing code is same as in question; snipped for brevity. ... }

    lvCanvas.TextRect(R, S, [tfSingleLine, tfEndEllipsis, tfCenter, tfVerticalCenter]);
    { ... End of original drawing code ... }

  finally
    lvCanvas.Free;
  end;
end;

这就是你想做的。只有第一列显示粗体,第二列显示斜体等,第二列和第三列不再有红色背景。

更新

如副本所示,使用原始 Sender.Canvas 并在每次更改字体设置时执行 lvCanvas.Refresh;,效果也很好。这对于 TControlCanvas 显然没有必要。因此,您可以使用 TControlCanvas 作为替代方案,尽管这会绑定更多资源。