.net 根据可用宽度和字体计算文本高度?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/901304/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Calculate text height based on available width and font?
提问by c00ke
We are creating PDF documents on the fly from the database using PDFsharp.
我们正在使用PDFsharp从数据库动态创建 PDF 文档。
I need to know the best way to calculate the height of the text area based on the font used and the available width.
我需要知道根据使用的字体和可用宽度计算文本区域高度的最佳方法。
I need to know the height so I can process page breaks when required.
我需要知道高度,以便在需要时处理分页符。
采纳答案by I liked the old Stack Overflow
In .NET you can call Graphics.MeasureString to find out how large the drawn text is going to be.
在 .NET 中,您可以调用 Graphics.MeasureString 来确定绘制的文本有多大。
Right, but when using PDFsharp you call XGraphics.MeasureString.
是的,但是在使用 PDFsharp 时,您会调用 XGraphics.MeasureString。
回答by Will Marcouiller
The PdfSharp.Drawing.XGraphics object has a MeasureString method that returns what you require.
PdfSharp.Drawing.XGraphics 对象有一个 MeasureString 方法,可返回您需要的内容。
var pdfDoc = new PdfSharp.Pdf.PdfDocument();
var pdfPage = pdfDoc.AddPage();
var pdfGfx = PdfSharp.Drawing.XGraphics.FromPdfPage(pdfPage);
var pdfFont = new PdfSharp.Drawing.XFont("Helvetica", 20);
while (pdfGfx.MeasureString("Hello World!").Width > pdfPage.Width)
--pdfFont.Size;
pdfGfx.DrawString("Hello World!", pdfFont
, PdfSharp.Drawing.XBrushes.Black
, new PdfSharp.Drawing.XPoint(100, 100));
This should help you. Please consider that I didn't test this code as I wrote it on the fly in order to help. It might contain some compile-time errors, but you may get the idea.
这应该对你有帮助。请注意,我没有测试这段代码,因为我是为了提供帮助而即时编写的。它可能包含一些编译时错误,但您可能会明白。
回答by Christian Lykke
I had a similiar problem so I implemented this extension method:
我有一个类似的问题,所以我实现了这个扩展方法:
public static double MeasureHeight(this PdfSharp.Drawing.XGraphics gfx, string text, PdfSharp.Drawing.XFont font, int width)
{
var lines = text.Split('\n');
double totalHeight = 0;
foreach (string line in lines)
{
var size = gfx.MeasureString(line, font);
double height = size.Height + (size.Height * Math.Floor(size.Width / width));
totalHeight += height;
}
return totalHeight;
}
回答by onedozenbagels
In .NET you can call Graphics.MeasureStringto find out how large the drawn text is going to be.
在 .NET 中,您可以调用Graphics.MeasureString来确定绘制的文本有多大。
回答by Eric H.
I wrote a small extension method to the XGraphic object to do just that : Calclulate the exact text height (and width) by specifiying the maxWidth. See the following gist for the code : https://gist.github.com/erichillah/d198f4a1c9e8f7df0739b955b245512a
我为 XGraphic 对象编写了一个小的扩展方法来做到这一点:通过指定 maxWidth 来计算确切的文本高度(和宽度)。请参阅以下代码要点:https: //gist.github.com/erichillah/d198f4a1c9e8f7df0739b955b245512a
回答by Wakka02
In case anyone still wants to find an answer, I've implemented a reasonably easy-to-understand method to find out the height of the resulting text.
如果有人仍然想找到答案,我已经实现了一种相当容易理解的方法来找出结果文本的高度。
Public Function PrintString(text As String, ft As XFont, rect As XRect, graph As XGraphics, b As SolidBrush, Optional tf As XTextFormatter = Nothing) As Integer
If Not IsNothing(tf) Then
tf.DrawString(text, ft, b, rect)
Else
Dim drawLeft As New XStringFormat
drawLeft.Alignment = XStringAlignment.Near
graph.DrawString(text, ft, b, rect, drawLeft)
End If
Dim width As Double = graph.MeasureString(text, ft).Width
Dim multiplier As Integer = 0
While width > 0
multiplier += 1
width -= rect.Width
End While
Dim height As Double = (graph.MeasureString(text, ft).Height) * multiplier
Return height
End Function
Explaining the code:
解释代码:
First, print the text. I included an Optional XTextFormatter called tf because I use either XGraphics or XTextFormatters interchangeably in my application.
首先,打印文本。我包含了一个名为 tf 的可选 XTextFormatter,因为我在我的应用程序中交替使用 XGraphics 或 XTextFormatters。
Then, calculate how long the text was by MeasureString().Width.
然后,通过 MeasureString().Width 计算文本的长度。
Then, calculate how many lines of text there were. This is done by dividing the total length of the text found earlier by the width of the provided rectangle (box) where the tax is printed. I did it with a while loop here.
然后,计算有多少行文本。这是通过将之前找到的文本的总长度除以提供的打印税款的矩形(框)的宽度来完成的。我在这里用了一个 while 循环。
Multiply the height of the text (using graph.MeasureString().Height) by the number of lines there were. This is the final height of your text.
将文本的高度(使用 graph.MeasureString().Height)乘以行数。这是文本的最终高度。
Return the height value. Now, calling the PrintString() function will print the text provided out while returning the height of the printed text afterward.
返回高度值。现在,调用 PrintString() 函数将打印提供的文本,同时返回打印文本的高度。
回答by I liked the old Stack Overflow
PDFsharp includes a class XTextFormatter that can be used to draw text with linebreaks.
PDFsharp 包含一个 XTextFormatter 类,可用于绘制带有换行符的文本。
However it can not determine the height needed for the text. Inspired by a comment from @Wakka02 I improved this class, generating class XTextFormatterEx.
In my opinion it also answers the original question, therefore I post an answer.
I know this is an old question and the answer may not help the OP, but it is a frequently asked question and the answer may help others.
但是它无法确定文本所需的高度。受到@Wakka02 评论的启发,我改进了这个类,生成了 XTextFormatterEx 类。
在我看来,它也回答了最初的问题,因此我发布了一个答案。
我知道这是一个老问题,答案可能对 OP 没有帮助,但这是一个常见问题,答案可能对其他人有帮助。
The new class has 500 lines of code - and I think this would be too much for this post.
新类有 500 行代码 - 我认为这对于这篇文章来说太多了。
The source code can be found on the PDFsharp forum:
http://forum.pdfsharp.net/viewtopic.php?p=9213#p9213
源代码可以在 PDFsharp 论坛上找到:http: //forum.pdfsharp.net/viewtopic.php?p=9213#p9213
It can also be found in my humble blog:
http://developer.th-soft.com/developer/pdfsharp-improving-the-xtextformatter-class-measuring-the-height-of-the-text/
它也可以在我不起眼的博客中找到:http:
//developer.th-soft.com/developer/pdfsharp-improving-the-xtextformatter-class-measuring-the-height-of-the-text/
When using the new class, you can first call PrepareDrawStringto find out how much of the text fits and which height the fitting text has. Then your decoder can draw the prepared text or prepare another text or prepare the same text with a different rectangle.
使用新类时,您可以先调用PrepareDrawString以了解适合文本的大小以及适合文本的高度。然后您的解码器可以绘制准备好的文本或准备另一个文本或用不同的矩形准备相同的文本。
My new class at work: XTextFormatterEx tf = new XTextFormatterEx(gfx); int lastCharIndex; double neededHeight;
我在工作的新课程:XTextFormatterEx tf = new XTextFormatterEx(gfx); int lastCharIndex; 双倍需要高度;
// Draw the text in a box with the optimal height
// (magic: we know that one page is enough).
XRect rect = new XRect(40, 100, 250, double.MaxValue);
//tf.Alignment = ParagraphAlignment.Left;
tf.PrepareDrawString(text, font, rect,
out lastCharIndex, out neededHeight);
rect = new XRect(40, 100, 250, neededHeight);
gfx.DrawRectangle(XBrushes.SeaShell, rect);
// Both variants should look the same.
// Optimized version: draw the prepared string.
tf.DrawString(XBrushes.Black, XStringFormats.TopLeft);
Preparing the text invokes MeasureString many times. Later the prepared text can be drawn without invoking MeasureString again.
准备文本会多次调用 MeasureString。稍后可以在不再次调用 MeasureString 的情况下绘制准备好的文本。
As of today (Juli 17, 2015) the class XTextFormatterEx (like the original XTextFormatter) uses internal fields of the XFont class. This requires special treatment when compiling the class. I decided to copy my XTextFormatterEx class into the PDFsharp folder after downloading the complete source package for PDFsharp 1.32.
Anybody trying to modify either the XTextFormatter or XTextFormatterEx class will face the same problem.
I hope this issue will be solved with future versions of PDFsharp, allowing modified versions of these classes to be included in the application project.
截至今天(2015 年 7 月 17 日),类 XTextFormatterEx(如原始 XTextFormatter)使用 XFont 类的内部字段。这在编译类时需要特殊处理。在下载了 PDFsharp 1.32 的完整源包后,我决定将我的 XTextFormatterEx 类复制到 PDFsharp 文件夹中。
任何试图修改 XTextFormatter 或 XTextFormatterEx 类的人都会面临同样的问题。
我希望未来版本的 PDFsharp 可以解决这个问题,允许将这些类的修改版本包含在应用程序项目中。
回答by rich p
The OP asked how to calculate text height based on available widthand font. Windows .NET provides an API call for this which takes a width argument; the version of PDFsharp I'm using (0.9.653, .NET 1.1) does not.
OP 询问如何根据可用宽度和字体计算文本高度。Windows .NET 为此提供了一个 API 调用,它接受一个宽度参数;我使用的 PDFsharp 版本(0.9.653,.NET 1.1)没有。
My solution - use the .NET API call with a Graphics object allocated for a custom-created Bitmap object to get the answer.
我的解决方案 - 将 .NET API 调用与为自定义创建的 Bitmap 对象分配的 Graphics 对象一起使用以获得答案。
What worked for me was to use a Bitmap that had 100 DPI resolution (critical) and happened to be the size of a Portrait page (probably less critical).
对我有用的是使用具有 100 DPI 分辨率(关键)并且恰好是纵向页面大小(可能不太关键)的位图。
Then I just asked .NET what the pixel size would be for painting on that bitmap.
然后我只是问 .NET 在该位图上绘制的像素大小是多少。
You probably will then want to convert the units from 1/100th of an inch to Points (for PDFsharp).
然后您可能希望将单位从 1/100 英寸转换为点(对于 PDFsharp)。
''' Adapted Code - this not tested or even compiled - Caveat Emptor!
''' Target: Visual Basic, .NET 1.1 (VS2003) [adapt as necessary]
' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
' GraphicsAlt.MeasureString() does substantially what System.Drawing MeasureString(...,Integer) does.
' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
Public Module GraphicsAlt
'
' Static data used Only to compute MeasureString() below.
'
' Cache a single copy of these two objects, to address an otherwise unexplained intermittent exception.
'
Private Shared myImage As Bitmap = Nothing
Private Shared myGraphics As Graphics = Nothing
Public Shared Function GetMeasureGraphics() As Graphics
If myImage Is Nothing Then
myImage = New Bitmap(1700, 2200) '' ... Specify 8.5x11
myImage.SetResolution(100, 100) '' ... and 100 DPI (if you want different units, you might change this)
myGraphics = Graphics.FromImage(myImage)
End If
Return myGraphics
End Function
'Given 1/100TH inch max width, return Rect to hold with units 1/100TH inch
'
Public Function MeasureString(ByVal text As String, ByVal aFont As System.Drawing.Font, ByVal width As Integer) As System.Drawing.SizeF
Return (GraphicsAlt.GetMeasureGraphics()).MeasureString(text, aFont, width)
End Function
End Module

