【问题标题】:Hard-coding Fonts in DotNETDotNET 中的硬编码字体
【发布时间】:2011-01-24 10:58:59
【问题描述】:

我在很多情况下都遇到过问题,因为用户没有在他们的机器上安装任何一种 Windows Core 字体(例如 Courier New、Comic Sans MS、Arial)。每当我尝试构建其中一种字体时,它都会引发错误,而不是退回到相关的,或者实际上是 any 其他字体。

如果我希望它是 Courier,但我并不特别喜欢它,那么构建 Font 的最佳方法是什么?

【问题讨论】:

    标签: .net fonts fallback construction


    【解决方案1】:

    您可以将字体作为资源嵌入并使用unsafe 关键字(并且必须使用'unsafe'编译)来获取字体...这是我用来将用户控件设置为字体的示例代码输入“OCR”

    私有 PrivateFontCollection pfc = new PrivateFontCollection(); 私人字体_fntOCRFont = null; 私有枚举 FontEnum{ OCR = 0 };

    这声明了一个私有的字体集合...字体'OCR'使用命名约定作为资源嵌入,其中'foo'是一个命名空间,因此资源名称将是'foo.ocraext.ttf'.. .看这里的“InitOCRFont”,它加载字体并将其添加到集合中:

    私人无效InitOCRFont(){ 尝试{ System.IO.Stream streamFont = this.GetType().Assembly.GetManifestResourceStream("foo.ocraext.ttf"); 如果(流字体!= null){ byte[] fontData = new byte[streamFont.Length]; streamFont.Read(fontData, 0, (int)streamFont.Length); streamFont.Close(); 不安全{ 固定(字节 *pFontData = fontData){ this.pfc.AddMemoryFont((System.IntPtr)pFontData, fontData.Length); } } }别的{ throw new Exception("错误!无法读取内置字体。"); } }catch(异常 eX){ throw new Exception("InitOCRFont 方法 - 发生异常!\n异常是:" + eX.Message); } }

    在这里,我设置了用户控件中的控件,通过遍历集合将字体设置为“OCR”字体,参见“InitializeCtlFont”,字体大小为 10,并且是粗体“字体”: 私人无效 InitializeCtlFont(){ this._fntOCRFont = new Font(this.pfc.Families[0], 10.0F, System.Drawing.FontStyle.Bold); if (this._fntOCRFont != null){ foreach(在 this.Controls 中控制 ctl){ if (ctl != null && ((ctl is Label) || (ctl is TextBox))){ ctl.Font = this._fntOCRFont; } } } }

    当用户控件被释放时,必须释放字体占用的资源,如Dispose方法中所示:

    尝试{ if (this._fntOCRFont != null) this._fntOCRFont.Dispose(); }抓住{ } 尝试{ if (this.pfc != null) this.pfc.Dispose(); }抓住{ }

    希望这会有所帮助, 最好的祝福, 汤姆。

    【讨论】:

    • 汤米,感谢您的精彩回复。恐怕这对我没有多大好处。我们不允许分发所有这些字体,我的应用程序应该是位深度不可知的,它甚至应该通过 Mono 在 Mac 上运行。我真诚地希望我不必求助于如此硬核的解决方案......
    • @David:我不确定Mac下的Mono是否会有PrivateFontCollection ....因为这是Windows特有的,无论如何,我想它是没用的....除非有一种更通用的方法......为了让纯跨平台工作,没有 pinvokes 和 Win32 特定的 API......
    【解决方案2】:

    嗯,你可以使用FontFamily.GenericMonospace 来获得a等宽字体,而不是专门的 Courier:

    Font f = new Font(FontFamily.GenericMonospace, 12, FontStyle.Regular);
    

    a few more such generic font families as well

    您也可以在尝试首选字体并遇到异常后将其用作最后的手段。

    【讨论】:

    • 谢谢 Johannes,我需要对此进行更多研究,看看是否可以应用它。
    【解决方案3】:

    这很不寻常。当您的程序请求目标计算机上不可用的字体时,Windows 字体映射器将始终提供替代字体。该替代字体通常是 XP 上的 Microsoft Sans Serif,更高版本上的 Segoe UI。这些都不会造成问题。

    再一次,如果机器非常混乱以至于它没有可用的核心字体,它可能根本没有可用的 TrueType 字体。是的,那会轰炸你的程序。坦率地说,这不是你应该处理的事情,除非这是一个真正有价值的客户。否则,您的客户支持团队可以轻松解决。

    【讨论】:

    • 嗨 nobugz,这已经发生了很多次,但似乎仅限于具有“奇怪”本地化(土耳其语、中文、韩语等)的人。我确实认为 Windows 字体回退逻辑应该防止它崩溃,但显然不是。不过感谢您的回复,这可能是暂时忽略此问题的最佳方法...
    • 呃,他们甚至使用的是 Windows 的许可副本吗?可能是葡萄酒之类的东西。不是你的问题。
    • nobugz,我不知道。如果我问他们,他们可能会撒谎。关键是,无论他们是否窃取了 Windows,他们我们的合法客户。修复当然不是那么困难(“只需安装字体 X”),但它确实激发了我对代码为什么会崩溃的好奇心。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-27
    • 2021-06-03
    相关资源
    最近更新 更多