如何将privatefontcollection内存中的字体呈现为可编辑的控件

这是将资源从资源加载到PrivateFontCollection导致损坏的延续

这里提供的答案足以用于具有UseCompatibleTextRendering方法的控件,但是它似乎不适用于其他常见控件,其中文本是主要焦点,例如:

  • 列表显示
  • 文本框
  • RichTextBox的
  • combobox
  • … 还有很多…

我已经尝试过这里的信息,这些信息基本上是用Program.csApplication.SetCompatibleTextRenderingDefault行进行的(没有人澄清默认情况下这个设置在哪里,所以我在这里记录它)。 我还玩过Telerik,DevExpress和Infragistics文本控件,除了Telerik之外没有内置兼容文本渲染的能力.Teleriks控件有这个方法,但它没有效果,包括无法将forecolor设置为存储的内容在属性(一个不同的动物,只是注意到Telerik radTextBox控件的毛刺)。

似乎无论我如何切片,任何对文本实际有用的控件都不会使文本正确显示正方形字符,如上面提到的原始post所示。

综上所述 :

  • 字体从资源加载到内存到PrivateFontCollection
  • 应用程序不会崩溃
  • 成功在标签上使用相同的字体(UseCompatibleTextRendering对它们起作用) – 在同一个表单上,在同一个项目中。

  • 受此(新?)问题影响的控件严格来说是任何可以“键入”的控件,如TextEdit,ListView,RichText,Combo等。

  • 当谈到切换,玩弄或玩耍时 – 这意味着我已经尝试了所提供的所有控件和/或代码的所有可能组合。 例如: Application.SetCompatibleTextRenderingDefault本身只有3种可能的组合。 (true) (false)或完全省略。 在完成这3个组合之后,我继续进行(基本故障排除,但我发现有必要解释所有基础)添加Telerik控件,然后尝试Telerik控件中的所有组合,以及Application.SetCompatibleTextRenderingDefault所有组合Application.SetCompatibleTextRenderingDefault命令。 测试的数量是指数级的,即渲染可能性的可能组合的数量乘以尝试的控制的数量乘以每个控件具有的渲染控制的可能性的数量,等等。

经过大量的挖掘,并且在这个问题上空无一人(包括仍然困扰我的这个问题的驱动器),我已经找到了解决这个问题的解决方案,它似乎已经面临许多问题并且也出现了问题 – 只需将字体作为文件安装在用户系统上即可。 正如我想的那样,这根本不是必需的,你可以用简单的方式嵌入字体,这样就可以在任何控件上使用它,包括TextBox,ComboBox等。无论你想要什么。

我将把它作为一个逐步指导来编写,如何将字体嵌入到您的项目中并使其在您想要的任何控件上正确显示。

第1步 – 选择受害者(字体选择)

出于演示目的(和流行的需求),我将使用FontAwesome字体(在撰写本文时为v 4.1)

  • 在项目内,转到Project > Properties
  • 单击“ Resources (应位于左侧)
  • 单击“ Add Resource按钮右侧的下拉箭头,然后选择“ Add Existing File

在此处输入图像描述

  • 确保从下拉列表中选择All Files (*.*) ,然后浏览到要嵌入的字体文件的位置,选择它,然后单击[打开]按钮。 在此处输入图像描述

您现在应该看到如下内容: 在此处输入图像描述

  • 按[CTRL] + [S]保存项目。

第2步 – 潜入代码

复制以下代码并将其另存为“MemoryFonts.cs”,然后将其添加到项目中

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices; using System.Drawing.Text; using System.Drawing; public static class MemoryFonts { [DllImport( "gdi32.dll" )] private static extern IntPtr AddFontMemResourceEx( IntPtr pbFont, uint cbFont, IntPtr pdv, [In] ref uint pcFonts ); private static PrivateFontCollection pfc { get; set; } static MemoryFonts() { if ( pfc==null ) { pfc=new PrivateFontCollection(); } } public static void AddMemoryFont(byte[] fontResource) { IntPtr p; uint c = 0; p=Marshal.AllocCoTaskMem( fontResource.Length ); Marshal.Copy( fontResource, 0, p, fontResource.Length ); AddFontMemResourceEx( p, (uint)fontResource.Length, IntPtr.Zero, ref c ); pfc.AddMemoryFont( p, fontResource.Length ); Marshal.FreeCoTaskMem( p ); p = IntPtr.Zero; } public static Font GetFont( int fontIndex, float fontSize = 20, FontStyle fontStyle = FontStyle.Regular ) { return new Font(pfc.Families[fontIndex], fontSize, fontStyle); } // Useful method for passing a 4 digit hex string to return the unicode character // Some fonts like FontAwesome require this conversion in order to access the characters public static string UnicodeToChar( string hex ) { int code=int.Parse( hex, System.Globalization.NumberStyles.HexNumber ); string unicodeString=char.ConvertFromUtf32( code ); return unicodeString; } } 

第3步 – 使它漂亮(使用字体)

  • 在主窗体上,从工具箱中添加TextBox控件 在此处输入图像描述

  • form_Load事件中,放入以下代码(在我的情况下,资源是fontawesome_webfont 。将其更改为您命名的字体资源)

     private void Form1_Load( object sender, EventArgs e ) { MemoryFonts.AddMemoryFont( Properties.Resources.fontawesome_webfont ); textBox1.Font = MemoryFonts.GetFont( // using 0 since this is the first font in the collection 0, // this is the size of the font 20, // the font style if any. Bold / Italic / etc FontStyle.Regular ); // since I am using FontAwesome, I would like to display one of the icons // the icon I chose is the Automobile (fa-automobile). Looking up the unicode // value using the cheat sheet https://fortawesome.github.io/Font-Awesome/cheatsheet/ // shows : fa-automobile (alias) [] // so I pass 'f1b9' to my UnicodeToChar method which returns the Automobile icon textBox1.Text = MemoryFonts.UnicodeToChar( "f1b9" ); } 

最终的结果

在此处输入图像描述


您可能会或可能不会注意到我使用此方法时请记住您可能希望添加多个嵌入字体。 在这种情况下,您只需为要添加的每个字体调用AddMemoryFont() ,然后在使用GetFont()时使用适当的索引值(基于零GetFont()

与Microsoft的UseCompatibleTextRendering ()文档相关的文档相反,您UseCompatibleTextRendering SetCompatibleTextRenderingDefault使用UseCompatibleTextRenderingSetCompatibleTextRenderingDefault 。 上面概述的方法允许在对象/控件中自然呈现字体。