8

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

我觉得我错过了什么;有没有更好的方法在页面上排版文本?我不介意使用第三方解决方案,只要它们可以免费供个人使用。

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

4

2 回答 2

19

WinForms

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

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

Windows 演示基础

如果您使用 WPF,这是完全不同的事情,因为您可以获得有关每个字形的详细几何信息。

但是,您可以将两者交错,有点乱,但可能。虽然,我不推荐它,因为图形和位图不能直接互换,这会导致性能下降。

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

您还将遇到其他一些挑战:

  1. WinForm 和 WPF 之间的字体列表并不相同(使用 WPF 的字体和字体类型更多)。
  2. 您不能只使用 WPF 字形并将其绘制到 WinForm 位图。
  3. 正如预期的那样,字形中的值是 inem因此需要根据点大小将它们转换为像素。

但是,您可以获得以下(不限于)信息:

在此处输入图像描述

所有详细信息(此处无法列出):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 作为排版引擎

一种可能的解决方法是使用 WebBrowser 控件进行设置。这不是真正的 hack,而是有点 hack-ish,因为它最初对用户计算机上的 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;
}

来自:从 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/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 等中生成所有文本和图形,并将结果保存为要显示的图像。

于 2013-07-10T00:27:43.103 回答
0

为了放下文字:有几种可能:

  1. 一个简单的标签,可让您进行简单的文本操作(如字体、位置、颜色等)
  2. 一个富文本文档,您可以更改控件的属性以满足您的需要,请记住,该文档可能会显示一些简单的图像等。
  3. 您可以使用图形对象和 onpaint 事件动态创建的图像->。不建议这样做,因为它是一种非常低级别的方法,但是正如您所知,您获得的级别越低,您获得的力量就越多。
  4. 许多控件的组合,在您创建的自定义控件中,您将要在本地成员中绘制/写入的信息保存在本地成员中 -> 然后在更改某些内容时保持继续,然后设置标志 ( _needToBeRepainted = true;),然后重新绘制,如果(_needToBeRepainted) 绘制一切。

如果您需要进一步的帮助来解决这个问题,请告诉我。

于 2013-07-09T12:49:55.003 回答