C#中的嵌入式资源字体无法正常工作

我在我的资源中嵌入了一个.ttf字体文件(特别是“Amatic Bold”),我使用下面的代码来获取Font。 我试过这篇文章的代码: 如何在我的C#应用​​程序中嵌入字体? (使用Visual Studio 2005)

这是我的实现:

static public Font GetCustomFont (byte[] fontData, float size, FontStyle style) { if (_fontCollection == null) _fontCollection = new PrivateFontCollection(); IntPtr fontPtr = System.Runtime.InteropServices.Marshal.AllocCoTaskMem(fontData.Length); System.Runtime.InteropServices.Marshal.Copy(fontData, 0, fontPtr, fontData.Length); _fontCollection.AddMemoryFont(fontPtr, fontData.Length); System.Runtime.InteropServices.Marshal.FreeCoTaskMem(fontPtr); return new Font(_fontCollection.Families[0], size, style); } 

我这样使用它:

 Font font = GetCustomFont(Properties.MainResources.Amatic_Bold, 25, System.Drawing.FontStyle.Bold); 

字体应如下所示: 在此处输入图像描述

问题是字体正在加载但在使用时没有正确显示; 它看起来像一个“Arial”或其他标准字体而不是它应该是什么。 如果我在Windows中安装该字体,它可以工作(我想很明显…)

我搜索了一个现有的答案,但无法找到我的确切问题……

任何帮助将不胜感激。 提前致谢。

那么,那……我想我明白了!

我将解释我“发现”的内容(无论是否显而易见):

  • 首先:对于要在控件中呈现的内存字体,必须将Application.SetCompatibleTextRenderingDefault设置为true 。 (也可以使用Control.UseCompatibleTextRendering )它在Microsoft文档中完美指定,但我错过了:-(

  • 第二: PrivateFontCollection.Families返回一组添加的字体,但是..惊喜! 按字母顺序排列! 无论您添加字体或您使用的方法( AddMemoryFont / AddFontFile )的顺序是什么,您都可以按字母顺序排序! 因此,如果您要添加多个字体,然后尝试获取已添加的最后一种字体,则可能会出错。

  • 第三:我也尝试在FreeCoTaskMem()添加字体或在表单关闭时执行FreeCoTaskMem() 。 两个都在为我工作! 我不知道这个的确切含义……

这是我的最终代码:

  //This list is used to properly dispose PrivateFontCollection after usage static private List _fontCollections; [STAThread] private static void Main(string[] args) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(true); //Mandatory in order to have Memory fonts rendered in the controls. //Dispose all used PrivateFontCollections when exiting Application.ApplicationExit += delegate { if (_fontCollections != null) { foreach (var fc in _fontCollections) if (fc != null) fc.Dispose(); _fontCollections = null; } }; Application.Run(new frmMain()); } void frmMain_Load(object sender, EventArgs e) { Font font1 = GetCustomFont(Properties.Resources.Amatic_Bold, 25, FontStyle.Bold); //or... Font font1 = GetCustomFont("Amatic-Bold.ttf", 25, FontStyle.Bold); labelTestFont1.Font = font1; Font font2 = GetCustomFont(Properties.Resources., 25, FontStyle.Bold); //or... Font font2 = GetCustomFont("", 25, FontStyle.Bold); labelTestFont2.Font = font2; //... } static public Font GetCustomFont (byte[] fontData, float size, FontStyle style) { if (_fontCollections == null) _fontCollections = new List(); PrivateFontCollection fontCol = new PrivateFontCollection(); IntPtr fontPtr = Marshal.AllocCoTaskMem(fontData.Length); Marshal.Copy(fontData, 0, fontPtr, fontData.Length); fontCol.AddMemoryFont(fontPtr, fontData.Length); Marshal.FreeCoTaskMem(fontPtr); //<-- It works! _fontCollections.Add (fontCol); return new Font(fontCol.Families[0], size, style); } static public Font GetCustomFont (string fontFile, float size, FontStyle style) { if (_fontCollections == null) _fontCollections = new List(); PrivateFontCollection fontCol = new PrivateFontCollection(); fontCol.AddFontFile (fontFile); _fontCollections.Add (fontCol); return new Font(fontCol.Families[0], size, style); } 

如您所见,我决定为每种字体创建一个独有的PrivateFontCollection,然后将其存储到List以便在应用程序端进行最终处理。

这是在3种不同的PC(都有Windows 7,32和64位)和3种不同的.ttf字体中测试过的。

结果的一个例子:

在此处输入图像描述

我不知道我的方法是否足够好,但我希望它对其他人有用!

还有一个细节:与我的预期不同,AddMemoryFont比AddFontFile慢(21ms vs 15 ms)

再次感谢所有评论!

问题可能是因为在使用fontfile时需要指定fontfamily exact font,编译器会切换到默认字体。 您可以从以下两种方法中了解您缺少的基本想法。

 var fontFile = new FontFamily("pack://application:,,,/Resources/#YourFont"); var typeface = new Typeface(new FontFamily(new Uri("pack://application:,,,/"), "/Resources/#YourFont"), FontStyles.Normal, FontWeights.Regular, FontStretches.Normal); var cultureinfo = new CultureInfo("en-us"); var ft = new FormattedText("YourText", cultureinfo, FlowDirection.LeftToRight, typeface, 28, Brushes.White) dc.DrawText(ft, new Point(0,0)); 

使用资源路径在客户端系统上安装字体。

 PrivateFontCollection yourfont = new PrivateFontCollection(); yourfont.AddFontFile("Your font Path"); label1.Font = new Font(yourfont.Families[0], 16, FontStyle.Regular);