PrintDocument
并使用PrintPageEventArgs
提供的Graphics
对象在页面上绘制文本,但是对于诸如字间距、行间距等方面几乎没有控制,并且许多工作都必须手动完成。我感觉自己缺少了什么;是否有更好的排版文本方式?只要个人免费,我不介意使用第三方解决方案。
这将用于排版各种小型文档,包括一页手册/传单(其中大部分文本是可变的,但图像是静态的),奖状证书(其中大部分文本和图像是静态的,但某些文本是可变的),时间表等。
PrintDocument
并使用PrintPageEventArgs
提供的Graphics
对象在页面上绘制文本,但是对于诸如字间距、行间距等方面几乎没有控制,并且许多工作都必须手动完成。使用 WinForms 很难做到良好的排版,几乎所有工作都必须手动完成。原因如下:
如果使用 WPF 就完全不同了,因为您可以获取每个字形的详细几何信息。
不过,你可以混用它们,虽然有些混乱,但是可以实现。但我不建议这样做,因为图形和位图不能直接互换,可能会导致性能缓慢。
如果想要尝试,请在项目中导入 System.Windows.Media
以访问 WPF 的字体和字形功能。
您还将遇到一些其他挑战:
em
为单位,因此需要根据点大小将其转换为像素。不过,您可以获得(不仅限于)以下信息:
所有细节(太多了,无法在这里列出):
http://msdn.microsoft.com/en-us/library/system.windows.media.glyphtypeface.aspx
但如果坚持使用 GDI+ 和 WinForms,则最好的方法可能是使用基于 GDI 的 TextMetrics 类。
您在任何情况下都可能遇到填充问题,不能设置字符间距等等。
您将需要通过使用 top + ascent 计算每个字体和大小的基线:
FontFamily ff = myFont.FontFamily;
float lineSpace = ff.GetLineSpacing(myFont.Style);
float ascent = ff.GetCellAscent(myFont.Style);
float baseline = myFont.GetHeight(ev.Graphics) * ascent / lineSpace;
PointF renderPt = new PointF(pt.X, pt.Y - baseline));
ev.Graphics.DrawString("My baselined text", myFont, textBrush, renderPt);
我不知道在WinForm环境中有任何第三方库能够做到这一点,我认为这是因为在这里提到的原因和它可能引起的麻烦。
总之,我只能建议您查看Windows Presentation Foundation / WPF以获得更好的排版效果,因为使用WinForms将会陷入许多妥协(我制作了一个字体查看器,那是我发现WPF的地方,因为我想显示字形和详细信息,包括黑匣子等-那已经够痛苦的了)。
更新:
解决这个问题的一个可能方法是使用WebBrowser控件进行设置。这不是一个实际的黑客,但是有点像黑客,因为它在用户计算机上建立了最初不必要的IE浏览器依赖关系。
然而,当涉及到排版时,这可能是灵活的,因为您对文本具有与任何HTML页面相同的简单控制。
要获得结果,请附加带有文本样式和属性的HTML。您甚至可以结合图像等内容(显然)。
该控件可以放置在另一个对用户不可见的隐藏表单上。
在将WebControl放置在表单上或手动创建它之后,可以通过单个步骤完成设置HTML:
WebBrowser1.DocumentText = "<span style='font-size:24px;'>Type-setting</span> <span style='font-family:sans-serif;font-size:18px;font-style:italic;'>using the browser component.</span>";
下一步是将您呈现为 HTML 的内容截取为图像,可以通过以下方式实现:
using mshtml;
using System.Drawing;
using System.Runtime.InteropServices;
[ComImport, InterfaceType((short)1), Guid("3050F669-98B5-11CF-BB82-00AA00BDCE0B")]
private interface IHTMLElementRenderFixed
{
void DrawToDC(IntPtr hdc);
void SetDocumentPrinter(string bstrPrinterName, IntPtr hdc);
}
public Bitmap GetImage(string id)
{
HtmlElement e = webBrowser1.Document.GetElementById(id);
IHTMLImgElement img = (IHTMLImgElement)e.DomElement;
IHTMLElementRenderFixed render = (IHTMLElementRenderFixed)img;
Bitmap bmp = new Bitmap(e.OffsetRectangle.Width, e.OffsetRectangle.Height);
Graphics g = Graphics.FromImage(bmp);
IntPtr hdc = g.GetHdc();
render.DrawToDC(hdc);
g.ReleaseHdc(hdc);
return bmp;
}
从:Saving images from a WebBrowser Control
现在,您可以将位图放置在普通页面上。..或者直接在表单上使用控件,但交互能力会降低(如果不注意,右键菜单可能会成为问题)。
由于不知道这是用于什么目的,因此这可能是一个合适的解决方案,但它提供了一些强大的选项,可代替第三方解决方案。
搜遍各处,似乎这个领域并没有受到那么多关注。我找到了一个接近的组件,但模式是相同的:用大锤子打钉子。它最终与WebBrowser解决方法处于同一类别。
这个组件确实是一个完整的编辑器,但通过禁用大部分功能,它也许可以用来显示格式化文本/图像,并且排版也算方便:
http://www.textcontrol.com/en_US/products/dotnet/overview/
另一种可能性是使用PDF组件设置内容,并使用组件将PDF呈现为图形(商业):
http://www.dynamicpdf.com/Generate-PDF-.NET.aspx
http://www.dynamicpdf.com/Rasterizer-PDF-.NET.aspx
非商业:
http://www.pdfsharp.net/?AspxAutoDetectCookieSupport=1
使用GhostScript获取图像:
http://www.codeproject.com/Articles/32274/How-To-Convert-PDF-to-Image-Using-Ghostscript-API
..或许有点老土,但无论如何,我将其包含在内,因为有时简单就是最好的选择 -
如果没有必要动态创建这些页面,则在Illustrator / Photoshop / inDesign等中生成所有文本和图形,并将结果保存为图像以供显示。
为了排版文本,有几种可能性:
_needToBeRepainted = true;
),然后在重新绘制时,如果(_needToBeRepainted)则绘制所有内容。如果您需要进一步的帮助解决此问题,请告诉我。