C# 用.NET排版文本

C# 用.NET排版文本,c#,.net,printdocument,typesetting,C#,.net,Printdocument,Typesetting,我正在编写一个WinForms.NET程序,需要在页面上放置一些文本(带有一些基本的几何/矢量图形)。是否存在与OS X和/或的等价物?到目前为止,我只是使用PrintDocument并使用PrintPageEventArgs提供的Graphics对象在页面上绘制文本,但对诸如字间距、行间间距等内容几乎没有控制权,很多事情都必须手动完成 我觉得我错过了什么;有没有更好的方式在页面上排版文本?我不介意使用第三方解决方案,只要它们是免费供个人使用的 这将用于排版少量文件,包括一页小册子/传单(其中大

我正在编写一个WinForms.NET程序,需要在页面上放置一些文本(带有一些基本的几何/矢量图形)。是否存在与OS X和/或的等价物?到目前为止,我只是使用
PrintDocument
并使用
PrintPageEventArgs
提供的
Graphics
对象在页面上绘制文本,但对诸如字间距、行间间距等内容几乎没有控制权,很多事情都必须手动完成

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


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

为了排版文本:有几种可能性:

  • 一个简单的标签,允许您进行简单的文本操作(如字体、位置、颜色等)
  • 一个富文本文档,您可以更改控件的属性以满足您的需要,请记住,此文档可能会显示一些简单的图像等
  • 图像->可以使用图形对象和onpaint事件动态创建。这是不推荐的,因为这是一个非常低级别的方法,但正如你所知道的,只要你获得低级别,你就会获得更多的权力
  • 许多控件的组合,在您创建的自定义控件中,保存要在本地成员中绘制/写入的信息->然后在更改某些内容时保持cont to,然后设置标志(
    \u needtoberepained=true;
    ),然后在重新绘制时,如果(\u needtoberepained)绘制所有内容
  • 如果您需要进一步帮助解决此问题,请告诉我。

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

  • 您无法获得详细的字形信息
  • 无论是GDI+还是基于GDI的版本,文本度量都非常不准确
  • Windows演示文稿基金会 如果您使用WPF,这是一个完全不同的问题,因为您可以获得关于每个glyph的详细几何信息

    但是,您可以将这两种方式交错,虽然有点混乱,但这是可能的。尽管如此,我不推荐它,因为图形和位图不能直接互换,这会导致性能下降

    如果您想了解是否可能需要将
    System.Windows.Media
    导入到项目中,以访问WPF的字体和字形功能

    您还将面临一些其他挑战:

  • WinForm和WPF之间的字体列表不相同(WPF有更多的字体和字体类型)
  • 您不能仅使用WPF图示符并将其绘制到WinForm位图
  • 与预期一样,图示符中的值位于
    em
    中,因此需要根据点大小将其转换为像素
  • 但是,您可以获得以下(但不限于)信息:

    所有详细信息(太多,无法在此列出):

    结论 但是如果您坚持使用GDI+和WinForms,那么您可以采取的最佳方法可能是使用基于GDI的类

    在任何情况下,您都可能会遇到填充问题,无法设置字符间距等等

    您必须使用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 as类型设置引擎 一个可能的解决方法是使用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>";
    
    发件人:

    现在,您可以将位图放在正常页面上……或者直接在表单上使用控件,减少交互功能(如果没有,右键单击菜单可能很容易成为问题)

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

    组件 从高处和低处看,这一区域似乎没有太多的目标。我可以找到一个接近的组件,但模式仍在继续:一个将用大锤敲打钉子。它最终与网络浏览者的工作属于同一类别

    该组件实际上是一个成熟的编辑器,但通过禁用其中的大部分功能,它可能可以简单地用于显示格式化的文本/图形,而类型设置就在眼前:

    另一种可能是使用PDF组件设置内容,并使用组件将PDF呈现为图形(商业):

    非商业性:

    使用重影脚本获取图像: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; }