【问题标题】:Delphi Printer.Canvas.TextWidth propertyDelphi Printer.Canvas.TextWidth 属性
【发布时间】:2011-07-29 01:25:05
【问题描述】:

我正在尝试使用我的 Delphi 应用程序设置打印的列宽。无论我为字符串键入什么内容都不会减少宽度。其实我不明白为什么该属性返回一个字符串,它应该返回以像素为单位的宽度。

我的代码是

Printer.Canvas.TextWidth('M');

编辑:我知道它不返回字符串,但“M”是什么意思?我要做的是使列变窄。我的代码位于sudrap.org/paste/text/19688

编辑:恐怕我无法清楚地解释问题,对不起。 我希望它像这样打印:

不是这样的:

【问题讨论】:

  • 但是TextWidth 应该返回整数。你在使用子句中使用Printers 单位吗?
  • 是的,我正在使用它。 “M”返回 75,“A”返回 61。我很困惑。
  • @nikel:我也不明白。 Canvas.TextWidth() 不是属性,它不返回字符串。它返回在画布上显示(打印)时字符串的宽度,以像素为单位。它不会更改字符串参数。您能否再发布几行代码?
  • 我明白,它返回整数。我只是想让列更小。我的代码:sudrap.org/paste/text/19688
  • @nikel - 这是守护进程的答案中提到的“自动换行”。你应该朝着那个方向前进。感谢您使问题清楚顺便说一句。 :)

标签: delphi printing canvas text-width


【解决方案1】:

尝试检查TextRect 功能。使用此功能,您可以指定要打印文本的目标矩形,这样您就可以缩小列。

uses Graphics;

var
  Text: string;
  TargetRect: TRect;
begin
  Printer.BeginDoc;

  Text := 'This is a very long text';

  // now I'll specify the rectangle where the text will be printed
  // it respects the rectangle, so the text cannot exceed these coordinates
  // with the following values you will get the column width set to 50 px

  TargetRect := Rect(Margin, Y, Margin + 50, Y + LineHeight);

  Printer.Canvas.Font.Size := 11;
  Printer.Canvas.Font.Name := 'Arial';
  Printer.Canvas.Font.Style := [fsBold];
  Printer.Canvas.TextRect(TargetRect, Text);

  Printer.EndDoc;
end;

除此之外,您可以使用formatting flagsTextRect 函数集获得它,它可以帮助您指定例如文本对齐、自动换行等。例如,如果您想在指定的矩形 [100;100]、[250;117] 中水平居中文本,可以使用以下方法。

Text := 'Centered text';
TargetRect := Rect(100, 100, 250, 117);
Printer.Canvas.TextRect(TargetRect, Text, [tfCenter]);

或者在您的情况下可能更有用的自动换行。这是一个矩形 [100;100], [200;134] 的示例,其中文本由 TextRect 函数自动换行。

Text := 'This is a very long text';
TargetRect := Rect(100, 100, 200, 134);
Printer.Canvas.TextRect(TargetRect, Text, [tfWordBreak]);

【讨论】:

  • 我几天前试过这个,但没有用。我记得它给出了错误。
  • 一件事是您需要在我的帖子中更新时将Graphics 添加到您的使用列表中。这就是你此时可能拥有的。第二件事是,我想,您正试图将Memo1.Text 之类的东西直接传递给TextRect 方法。虽然这个方法有两个版本,我在示例中使用的那个需要声明 Text 参数,其定义中的 var 关键字是什么var Text: string;
【解决方案2】:

如果您在画布上使用固定宽度的字体,您应该对所有单字符串得到相同的结果。如果使用可变宽度字体,每个字符将返回不同的宽度。

Printer.Canvas.Font.Name = 'Courier New';
Printer.Canvas.Font.Size = 13;
ColumnWidth := Printer.Canvas.TextWidth('M');

对于不同的字体或不同的字体大小,你会得到不同的结果。

【讨论】:

  • 我猜它与字体大小没有任何关系。因为我只需要使列更窄。所以右列将是免费的。
  • 现在我很困惑。你为什么要问 TextWidth?
  • 我希望 TextWidth 属性能解决这个问题。
【解决方案3】:

我不明白你怎么说它返回文本。如果它返回文本,您的代码甚至无法编译,当您尝试将数字乘以文本时,您会遇到错误。您甚至可以将其转换为字符串以供显示。

您是否被以下事实误导了:使用可变宽度字体,您会针对不同的字符串得到不同的答案?您甚至可以以不同的顺序为相同的字母获得不同的答案。对于某些字体,“WAM”会产生与“WMA”不同的答案,因为 W 和 A 是如何组合在一起的。

此外,您只是假设标签的宽度小于 15 M。虽然这通常是这种情况,但它不是一个好的编程习惯。相反,您应该询问每个标签的宽度,并使用略高于最大答案的东西。

最后,您对 LineHeight 的处理非常糟糕。如果这是您真正想要的,只需将 300 添加到 y 虽然它应该是您的行高的一些倍数,而不是固定值。您将在具有不同 DPI 设置的打印机上使用打码获得非常不同的结果。

您是否尝试过使用调试器单步执行此代码以查看内部发生了什么?您将位置输出到打印输出表明您没有使用调试器。

【讨论】:

  • +1;还有关于获得保证金的问题,例如this post 尽管 Escape 函数的用法已经过时,但它会比 5 * width of upper cased M 精确得多,但它会完全超出这个问题;)
  • 感谢您的详细回答。前几天我尝试将 300 添加到 y ,但没有成功。我无法理解这与标签有什么关系。以及如何启用调试?
  • @nikel:无需启用调试。你只需在你想要的地方设置一个断点,它会在到达那里时停止。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-06
  • 2020-09-30
  • 1970-01-01
相关资源
最近更新 更多