使用.NET排版文本

dre*_*lax 8 .net c# printdocument typesetting

我正在编写一个WinForms .NET程序,需要在页面上放置一些文本(带有一些基本的几何/矢量图形).是否有相当于OS X的核心图形和/或核心文本?到目前为止,我只是使用a PrintDocument并使用Graphics提供的对象PrintPageEventArgs在页面上绘制文本,但是对于诸如字间距,行间距等内容的控制很少,并且必须手动完成许多工作.

我觉得我错过了一些东西; 有没有更好的方法来排版页面上的文字?我不介意使用第三方解决方案,只要它们是免费供个人使用.

这将用于排版少量文档,包括单页小册子/传单(大多数文本是可变的但图像是静态的),奖励证书(大多数文本和图像是静态的,但有些文本是可变的),时间表,等等

小智 18

的WinForms

当你使用WinForms时,几乎不可能进行正确的类型设置,是的,几乎所有东西都必须手动完成.这有几个原因:

  1. 您没有获得详细的字形信息
  2. 文本测量是非常不准确的,无论是GDI +还是基于GDI的版本.

Windows Presentation Foundation

如果你使用WPF,这是一个完全不同的事情,因为你得到关于每个字形的详细几何信息.

但是,你可以交错这两个,有点乱,但可能.虽然,我不推荐它,因为图形和位图不能直接互换,这可能导致性能降低.

如果您想查看System.Windows.Media将项目导入项目以访问WPF的字体和字形功能的可能性.

您还将遇到其他几个挑战:

  1. WinForm和WPF之间的字体列表不相同(使用WPF的字体和字体类型更多).
  2. 您不能只使用WPF字形并将其绘制到WinForm位图.
  3. 正如预期的那样,字形中的值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);
Run Code Online (Sandbox Code Playgroud)

我不知道任何可以在WinForm环境中执行此操作的第三方库,我相信这里提到的原因以及它会带来的痛苦.

总而言之,我只能建议你看一下Windows Presentation Foundation/WPF,以便更好地实现正确的类型设置,因为你会遇到很多使用WinForms的妥协(我做了一个字体查看器,这是我的地方遇到了WPF,因为我想展示字形和有关它的详细信息,包括黑盒等等 - 这很痛苦.

更新:

WebBrowser作为类型设置引擎

可能的解决方法是使用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>";
Run Code Online (Sandbox Code Playgroud)

下一步是将您呈现为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;
}
Run Code Online (Sandbox Code Playgroud)

发件人:从WebBrowser控件保存图像

现在,您可以将位图放在普通页面上...或者只是直接在窗体上使用控件,交互能力降低(如果没有,右键菜单很容易成为问题).

不知道这是用于什么的确切用法,这可能是也可能不是一个合适的解决方案,但它提供了一些强大的选项,可以代替第三方解决方案.

组件

看起来高低似乎这个区域没有那么多的目标.我可以找到一个接近的组件,但模式仍在继续:一个人将用大锤击打钉子.它最终与WebBrowser解决方法相同.

这个组件实际上是一个完全成熟的编辑器,但是通过禁用其中的大部分,它可以用于简单地显示带有类型设置的格式化文本/图形:

http://www.textcontrol.com/en_US/products/dotnet/overview/

另一种可能性是使用PDF组件设置的内容和使用组件来渲染PDF图形(商业):
http://www.dynamicpdf.com/Generate-PDF-.NET.aspx
HTTP:// WWW .dynamicpdf.com /光栅-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

明显的静态替代方案

..或corky也许,但无论如何我会包括它,因为简单有时最好 -

如果不能动态创建这些页面,则在Illustrator/Photoshop/inDesign等中生成所有文本和图形,并将结果保存为要显示的图像.

  • 这里肯定有足够的信息指出我正确的方向.+500给你! (2认同)