在C#的Windows.Form中使用自定义.ttf字体

13

我如何在当前的Windows.Forms应用程序中使用自定义.ttf字体文件?我在某个地方读到说我需要将其用作嵌入资源,但是我该如何设置System.Drawing.Font类型呢?

3个回答

14

本文:如何嵌入 True Type 字体,展示了如何在 .NET 中实现所需要的功能。

如何嵌入 True Type 字体

出于美学或特定视觉样式等原因,某些应用程序会嵌入某些不太常见的字体,以确保无论目标系统是否已安装该字体,都可以随时使用。

这里有两个秘诀。首先,需要将字体添加到解决方案并将其标记为嵌入式资源,以便将其放置在资源中。其次,在运行时,通过流加载字体,并将其存储在 PrivateFontCollection 对象中以供后续使用。

此示例使用了一种您的系统很可能没有安装的字体。Alpha Dance 是从免费字体收藏中获取的免费 True Type 字体。将此字体添加到解决方案中,并在属性中选择“嵌入式资源”构建操作即可将其嵌入到应用程序中。

图1:Alpha Dance 字体文件嵌入到解决方案中。

一旦文件已成功包含在资源中,您需要提供一个 PrivateFontCollection 对象来存储它,并提供一种方法将其加载到集合中。最好的位置可能是窗体加载覆盖或事件处理程序。以下代码显示了此过程。请注意如何使用 AddMemoryFont 方法。它需要指向字体保存为字节数组的内存指针。在 C# 中,我们可以使用 unsafe 关键字方便地实现此目的,但 VB 必须使用 Marshal 类的不受管控内存处理功能。当然,后一种选项也适用于不喜欢 unsafe 关键字的 C# 程序员。

PrivateFontCollection pfc = new PrivateFontCollection();
private void Form1_Load(object sender, System.EventArgs e)
{
  Stream fontStream = this.GetType().Assembly.GetManifestResourceStream("embedfont.Alphd___.ttf");

  byte[] fontdata = new byte[fontStream.Length];
  fontStream.Read(fontdata,0,(int)fontStream.Length);
  fontStream.Close();
  unsafe
  {
    fixed(byte * pFontData = fontdata)
    {
      pfc.AddMemoryFont((System.IntPtr)pFontData,fontdata.Length);
    }
  }
}

字体可能仅提供某些可用的样式,选择不存在的字体样式将会抛出异常。为了解决这个问题,可以查询字体以查看哪些样式可用,并且只使用该字体提供的样式。以下示例演示了如何使用Alpha Dance字体来检查可用的字体样式并显示所有存在的样式。请注意,下划线和删除线样式是由字体渲染引擎构建的伪样式,实际上并没有以字形形式提供。

private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
  bool bold=false;
  bool regular=false;
  bool italic=false;

  e.Graphics.PageUnit=GraphicsUnit.Point;
  SolidBrush b = new SolidBrush(Color.Black);

  float y=5;

  System.Drawing.Font fn;

  foreach(FontFamily ff in pfc.Families)
  {
    if(ff.IsStyleAvailable(FontStyle.Regular))
    {
      regular=true;
      fn=new Font(ff,18,FontStyle.Regular);
      e.Graphics.DrawString(fn.Name,fn,b,5,y,StringFormat.GenericTypographic);
      fn.Dispose();
      y+=20;
    }
    if(ff.IsStyleAvailable(FontStyle.Bold))
    {
      bold=true;
      fn=new Font(ff,18,FontStyle.Bold);
      e.Graphics.DrawString(fn.Name,fn,b,5,y,StringFormat.GenericTypographic);
      fn.Dispose();
      y+=20;
    }
    if(ff.IsStyleAvailable(FontStyle.Italic))
    {
      italic=true;
      fn=new Font(ff,18,FontStyle.Italic);
      e.Graphics.DrawString(fn.Name,fn,b,5,y,StringFormat.GenericTypographic);
      fn.Dispose();
      y+=20;
    }
    if(bold  && italic)
    {
      fn=new Font(ff,18,FontStyle.Bold | FontStyle.Italic);
      e.Graphics.DrawString(fn.Name,fn,b,5,y,StringFormat.GenericTypographic);
      fn.Dispose();
      y+=20;
    }
    fn=new Font(ff,18,FontStyle.Underline);
    e.Graphics.DrawString(fn.Name,fn,b,5,y,StringFormat.GenericTypographic);
    fn.Dispose();
    y+=20;
    fn=new Font(ff,18,FontStyle.Strikeout);
    e.Graphics.DrawString(fn.Name,fn,b,5,y,StringFormat.GenericTypographic);
    fn.Dispose();
  }

  b.Dispose();
}

图2展示了应用程序的操作。

图2. 内置的Alpha Dance字体。

请参考Form1_Paint事件处理程序,它具体展示如何设置System.Drawing.Font类型,基于使用System.Drawing.Text.PrivateFontCollection类。

希望这个能有所帮助。


3

通过p/invoke使用AddFontResourceEx API函数,传递FR_PRIVATE参数以防止安装全局字体。然后,您应该能够像往常一样将字体名称传递给Font构造函数。

编辑:如果您使用PrivateFontCollection并从外部文件加载字体,则甚至不需要这样做。如果您从嵌入的资源加载字体,请使用Ash的解决方案。


1
有没有示例可以参考?我真的看不懂MSDN链接。谢谢你的帮助。 - kthakore

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接