我用的是 Delphi 11火猴我尝试只使用TPrinter.Canvas
方法进行一些打印(文本、形状、位图)。一切正常。
但是还有一个叫做TTextLayout
的东西,它对格式化文本非常有用。然而,当我尝试使用这个类打印时,我看不到任何文本。另一方面,在常规画布上绘制,如使用TTextLayout
的TPaintBox.Canvas
或TBitmap.Canvas
,效果很好。
下面是我的代码(TButton
(×3),TPaintBox
,TPrintDialog
,TSaveDialog
):
uses
FMX.TextLayout;
procedure TForm1.Button1Click(Sender: TObject);
begin
PaintBox1.Repaint;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
DoPrint;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
DrawToFile;
end;
procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
begin
DrawSomething(Canvas);
end;
procedure TForm1.DoPrint;
begin
if PrintDialog1.Execute then begin
Printer.ActivePrinter.SelectDPI(1200, 1200);
Printer.Orientation := TPrinterOrientation.poLandscape;
Printer.BeginDoc;
try
if Printer.Canvas.BeginScene() then try
DrawSomething(Printer.Canvas);
finally
Printer.Canvas.EndScene;
end;
finally
Printer.EndDoc;
end;
end;
end;
procedure TForm1.DrawToFile;
var
Bmp: TBitmap;
begin
if SaveDialog1.Execute then begin
Bmp := TBitmap.Create(300, 300);
try
Bmp.Clear(TAlphaColors.White);
if Bmp.Canvas.BeginScene() then try
DrawSomething(Bmp.Canvas);
finally
Bmp.Canvas.EndScene;
end;
Bmp.SaveToFile(SaveDialog1.FileName);
finally
Bmp.Free;
end;
end;
end;
procedure TForm1.DrawSomething(Canvas: TCanvas);
var
tl: TTextLayout;
BoldFont: TFont;
StrokeBrush: TStrokeBrush;
begin
tl := nil;
BoldFont := nil;
StrokeBrush := nil;
try
tl := TTextLayoutManager.DefaultTextLayout.Create();
BoldFont := TFont.Create;
StrokeBrush := TStrokeBrush.Create(TBrushKind.Solid, TAlphaColors.Blue);
BoldFont.SetSettings('Arial', 96, TFontStyleExt.Create([TFontStyle.fsBold]));
StrokeBrush.Thickness := 10.0;
tl.BeginUpdate;
try
tl.TopLeft := TPointF.Create(0,0);
tl.MaxSize := TPointF.Create(300, 300);
tl.Text := 'Lorem'#$0A'ipsum';
tl.WordWrap := True;
tl.HorizontalAlign := TTextAlign.Leading;
tl.VerticalAlign := TTextAlign.Leading;
tl.Color := TAlphaColors.Black;
tl.Font.SetSettings('Arial', 96, TFontStyleExt.Create([]));
tl.Opacity := 1.0;
tl.AddAttribute(TTextRange.Create(3, 5), TTextAttribute.Create(BoldFont, TAlphaColors.Black));
finally
tl.EndUpdate;
end;
tl.RenderLayout(Canvas);
Canvas.DrawLine(TPointF.Create(10, 20), TPointF.Create(110, 120), 1.0, StrokeBrush);
finally
StrokeBrush.Free;
BoldFont.Free;
tl.Free;
end;
end;
字符串Button1
重新绘制TPaintBox
,Button2
打印,Button3
创建图像文件。以下是我的结果:
适用范围:Application screenshot
Microsoft Print to PDF(从实际打印机获得相同的结果):PDF screenshot的
图像文件:Image file
正如您所看到的,TControl.Canvas
和TBitmap.Canvas
在呈现文本布局方面都没有问题。只有打印机的画布不显示文本。我做错什么了吗?
2条答案
按热度按时间lfapxunr1#
它不起作用,因为
TTextLayout.RenderLayout(Canvas)
调用TTextLayoutD2D.DoDrawLayout
,TTextLayoutD2D.DoDrawLayout
需要TCanvasD2D
画布,而打印机画布可能不是:字符串
这可能会导致Embarcadero的bug报告,但同时,一种解决方法是将文本绘制到
TBitMap
(就像您已经使用Button3
一样),并将该位图绘制到打印机画布:型
NB:不是
try...finally
的常规用户,我不知道我是否有最好的安排。relj7zay2#
感谢@Philip J。Rayment的回答,我设法找到了另一个解决方案。
TTextLayout
的创建有问题:DefaultTextLayout
返回运行平台的默认文本布局类(documentation)。这通常与打印机所需的不同。在这种情况下,我们需要使用TTextLayoutManager.TextLayoutByCanvas()
方法。字符串
但是,不同类型的画布的文本布局行为不同。例如,GDI+不支持文本属性(一个文本中的不同文本格式):
| 我的解决方案没有位图| My solution without bitmap |
| --| ------------ |
|
的|
|
布局也有不同的填充,因此,启用自动换行和太小的
MaxSize
,你可能会得到相当意想不到的结果(这次删除格式):| 我的解决方案没有位图| My solution without bitmap |
| --| ------------ |
|
的|
|
使用相同的设置,但不同的
TTextLayout
类。这有点尴尬,因为人们会期望后代仅仅充当“ Package 器”并产生相同的结果。
所以,我认为菲利普的解决方案比这个更好。尽管如此,
DefaultTextLayout
仍然可能在不同的平台上返回不同的文本布局。也许有一天,Embarcadero会修复TTextLayout
的行为。