Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#中嵌入的资源字体无法正常工作_C#_Winforms_Fonts_Embedded Resource - Fatal编程技术网

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

C#中嵌入的资源字体无法正常工作,c#,winforms,fonts,embedded-resource,C#,Winforms,Fonts,Embedded Resource,我在我的资源中嵌入了一个.ttf字体文件(“特别是Amatic Bold”),我正在使用下面的代码来获取字体。 我试过这篇文章的代码: 这是我的实现: static public Font GetCustomFont (byte[] fontData, float size, FontStyle style) { if (_fontCollection == null) _fontCollection = new PrivateFontCollection();

我在我的资源中嵌入了一个.ttf字体文件(“特别是Amatic Bold”),我正在使用下面的代码来获取字体。 我试过这篇文章的代码:

这是我的实现:

    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中安装字体,它会工作(我想很明显…)

我搜索了一个已有的答案,但找不到确切的问题,

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

问题可能是因为在使用fontfile时需要指定fontfamily精确字体,编译器会切换到默认字体。 您可以通过以下两种方法了解您所缺少的内容。

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);

那么。。。我想我明白了

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

  • 首先:
    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);
    }
//此列表用于在使用后正确处理PrivateFontCollection
静态私有列表fontCollections;
[状态线程]
私有静态void Main(字符串[]args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(true);//必须这样才能在控件中呈现内存字体。
//退出时处置所有使用的PrivateFontCollections
Application.ApplicationExit+=委托{
如果(_fontCollections!=null){
如果(fc!=null)fc.Dispose(),则为foreach(在fontCollections中为var fc);
_fontCollections=null;
}
};
运行(新的frmMain());
}
无效frmMain_加载(对象发送方,事件参数e)
{
Font font1=GetCustomFont(Properties.Resources.Amatic_Bold,25,FontStyle.Bold);
//或者。。。
Font font1=GetCustomFont(“Amatic Bold.ttf”,25,FontStyle.Bold);
labelTestFont1.Font=font1;
Font font2=GetCustomFont(Properties.Resources.,25,FontStyle.Bold);
//或者。。。
Font font2=GetCustomFont(“”,25,FontStyle.Bold);
labelTestFont2.Font=font2;
//...
}
静态公共字体GetCustomFont(字节[]fontData、浮点大小、FontStyle样式)
{
如果(_fontCollections==null)_fontCollections=new List();
PrivateFontCollection fontCol=新PrivateFontCollection();
IntPtr fontPtr=Marshal.alloctaskmem(fontData.Length);
封送处理副本(fontData,0,fontPtr,fontData.Length);
fontCol.AddMemoryFont(fontPtr,fontData.Length);

FreeCoTaskMem元帅(fontPtr);//这种可怕的错误代码就像病毒一样,非常难以清除。你是通过字体保存的,它是OpenType字体。只能在WPF或Direct2D应用程序中使用。字体映射器找到了一种可以在Winforms应用程序中工作的替代品。谢谢,@HansPassant。有没有什么好的替代方法可以不用安装字体它?当您安装字体时,它实际工作吗?然后修复此代码中的错误。在无法再使用字体并且调用了._fontCollection.Dispose()方法和_fontCollection.Families[0]之前,您不能调用Marshal.FreeCoTaskMem()始终返回第一种字体,而不是最后加载的字体。好的,我会尝试。我知道_fontCollection.Families[0]问题,这是我最初计划的行为,尽管我将对其进行修改。再次感谢。Adam,您需要重新组织内存管理,以便创建字体集合,
AllocTaskMem
AddMemoryFont
仅一次,然后仅在窗体/控件不可用时处置字体集合和
FreeCoTaskMem
一次姿势。如果您试图在控件上使用字体,则对兼容文本呈现有一些要求-如果这是错误的,则字体将被忽略。谢谢,@Jerin,我会尝试一下。非常感谢,Control.UseCompatibleTextRendering是我在使用AddMemoryFont这么多小时后解决问题的方法!!