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

Ada*_*ohl 5 c# fonts embedded-resource winforms

我在资源中嵌入了一个.ttf字体文件(特别是“ Amatic Bold”),并在下面使用此代码获取字体。我在这篇文章中尝试了以下代码:如何在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);
    }
Run Code Online (Sandbox Code Playgroud)

我这样使用它:

Font font = GetCustomFont(Properties.MainResources.Amatic_Bold, 25, System.Drawing.FontStyle.Bold);     
Run Code Online (Sandbox Code Playgroud)

字体应如下所示: 在此处输入图片说明

问题是字体正在加载,但使用时无法正确显示。它看起来像“ Arial”或其他标准字体,而不是应有的字体。如果我将字体安装在Windows中,则可以正常工作(我想很明显...)

我搜索了现有的答案,但找不到确切的问题...

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

Ada*_*ohl 9

那么……我想我明白了!

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

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

  • 第二:PrivateFontCollection.Families返回一组添加的字体,但是.. 惊喜!它是按字母顺序排列的!无论您添加字体的顺序或使用的方法 ( AddMemoryFont/ AddFontFile) 是什么,您都会按字母顺序排列!因此,如果您添加了不止一种字体,然后试图获取您添加的最后一种字体,您可能会得到错误的字体。

  • 第三:我也尝试过FreeCoTaskMem()在集合中添加字体或在关闭表单时进行。两者都为我工作!我不知道这的确切含义......

这是我的最终代码:

    //This list is used to properly dispose PrivateFontCollection after usage
    static private List<PrivateFontCollection> _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.<font_resource>, 25, FontStyle.Bold);
        //or...
        Font font2 = GetCustomFont("<font_filename>", 25, FontStyle.Bold);

        labelTestFont2.Font = font2;

        //...

    }
    static public Font GetCustomFont (byte[] fontData, float size, FontStyle style)
    {
        if (_fontCollections == null) _fontCollections = new List<PrivateFontCollection>();
        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>();
        PrivateFontCollection fontCol = new PrivateFontCollection();
        fontCol.AddFontFile (fontFile);
        _fontCollections.Add (fontCol);
        return new Font(fontCol.Families[0], size, style);
    }
Run Code Online (Sandbox Code Playgroud)

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

这在 3 种不同的 PC(均使用 Windows 7、32和 64 位)和 3 种不同的.ttf字体中进行了测试。

结果示例:

在此处输入图片说明

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

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

再次感谢所有评论!