为什么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;
但结果不如预期:
第二列中的文本应为斜体,但不应为粗体且背景为绿色。
第三列中的文本应加下划线,但不能是粗体和蓝色背景。
- 使用
TextOut
而不是 TextRect
进行文本绘制会得到相同的结果。
- 我已经在 delphi-xe5 中尝试 运行 这个测试项目,但结果是一样的。
- 所有列中的文本背景颜色始终与第一列中的相同。
谁能给我解释一下这是怎么回事?
我也试过了,确实不行。 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
作为替代方案,尽管这会绑定更多资源。
我正在尝试使用自定义字体样式和背景颜色在列表视图中绘制项目。表单上有一个默认的列表视图。我已将 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;
但结果不如预期:
第二列中的文本应为斜体,但不应为粗体且背景为绿色。 第三列中的文本应加下划线,但不能是粗体和蓝色背景。
- 使用
TextOut
而不是TextRect
进行文本绘制会得到相同的结果。 - 我已经在 delphi-xe5 中尝试 运行 这个测试项目,但结果是一样的。
- 所有列中的文本背景颜色始终与第一列中的相同。
谁能给我解释一下这是怎么回事?
我也试过了,确实不行。 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
作为替代方案,尽管这会绑定更多资源。