[英]System.Drawing.Font not working as expected
I'm trying to use a private font (PrivateFontCollection) to change a RichTextBox font.我正在尝试使用私有字体 (PrivateFontCollection) 来更改 RichTextBox 字体。 The problem is, the program recognizes the font when I pass the path to it but, when I change the RTB font, it doesn't work and instead it uses Calibri .
问题是,当我将路径传递给程序时,程序会识别字体,但是当我更改 RTB 字体时,它不起作用,而是使用Calibri 。
The code is very simple:代码非常简单:
var RTB = new System.Windows.Forms.RichTextBox();
var privateFont = new System.Drawing.Text.PrivateFontCollection();
privateFont.AddFontFile(@"path.ttf");
RTB.SelectAll();
RTB.SelectionFont = new System.Drawing.Font(privateFont.Families[0], 12);
I'm using it to format a RTF text file.我正在使用它来格式化 RTF 文本文件。 When I generate the file it comes out with the Calibri font.
当我生成文件时,它带有 Calibri 字体。 And what intrigues me the most is, if I change the
privateFont.AddFontFile(@"path.ttf");
最让我感兴趣的是,如果我更改
privateFont.AddFontFile(@"path.ttf");
to Arial , for example, the text is returned in the font I wanted, but not the whole text, the end of the text is returned in Calibri .以Arial为例,文本以我想要的字体返回,但不是整个文本,文本的结尾以Calibri返回。
I don't know what is happening here.我不知道这里发生了什么。
To answer your question of "what is happening here", for a font to be recognized in an exported RTF file requires that the font either be installed as a system font or<\/em> manually embedded in the file that you are exporting from the RichTextBox<\/code> .<\/i>
要回答“这里发生了什么”的问题,要在导出的 RTF 文件中识别字体,需要将该字体作为系统字体安装或<\/em>手动嵌入到您从
RichTextBox<\/code>导出的文件中。<\/b> The former seems less dicey and the three ways I know of to make the font be installed are:<\/i>前者似乎不那么冒险,我知道的三种安装字体的方法是:<\/b><\/p>
![](/img/trans.png)
Manual -<\/strong> Right-click on yourcustomfont.ttf<\/strong> and select Install<\/strong> .<\/i>手动 -<\/strong>右键单击 yourcustomfont.ttf<\/strong>并选择Install<\/strong> 。<\/b><\/li>
![](/img/trans.png)
Deploy -<\/strong> If your application is packaged in something like an .msi then your installer should be able to install fonts.<\/i>部署 -<\/strong>如果您的应用程序打包在 .msi 之类的文件中,那么您的安装程序应该能够安装字体。<\/b> (This is something I've actually done in the past and I know from my own experience that it works).<\/i> (这是我过去实际做过的事情,我从自己的经验中知道它有效)。<\/b><\/li>
Proposed solution -<\/strong> Using this answer How to test if a Font is installed<\/a> run a one-time font installation when the MainForm<\/code> ctor is initially run.<\/i>建议的解决方案 -<\/strong>使用此答案
如何测试是否安装<\/a>了字体在MainForm<\/code> ctor 最初运行时运行一次性字体安装。<\/b> The code below checks for the presence of a font named smiley.ttf<\/strong> and invokes this Windows system installer dialog if it's not:<\/i>下面的代码检查是否存在名为smiley.ttf<\/strong>的字体,如果不存在则调用此 Windows 系统安装程序对话框:<\/b><\/li><\/ul>
![](/img/trans.png)
TESTBENCH<\/strong><\/i>试验台<\/strong><\/b><\/p>
![](/img/trans.png)
public MainForm() { InitializeComponent(); var path = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "Fonts", "smiley.ttf"); privateFontCollection.AddFontFile(path); var fontFamily = privateFontCollection.Families[0]; Debug.Assert(fontFamily.Name == "smiley", "Expecting 'smiley' is the font family name"); var font = new Font(fontFamily, 12F); richTextBox1.Text = "\"; richTextBox1.AppendText(Environment.NewLine); richTextBox1.Select(0, 1); richTextBox1.SelectionFont = font; var privateFontName = font.Name; \/\/ Returns INCORRECT name of private font var selectionFontName = richTextBox1.SelectionFont.Name; \/\/ Returns CORRECT name of private font. var selectionOriginalFontName = richTextBox1.SelectionFont.OriginalFontName; richTextBox1.SelectionBackColor = Color.Yellow; richTextBox1.AppendText($"PrivateFont={privateFontName}{Environment.NewLine}"); richTextBox1.AppendText($"SelectionFont.Name={selectionFontName}{Environment.NewLine}"); richTextBox1.AppendText($"SelectionFont.OriginalFontName={selectionOriginalFontName}{Environment.NewLine}"); richTextBox1.Select(int.MaxValue, 0); \/\/ But the private font name is read back correctly \/\/ when its used for the Font property of a RichTextBox richTextBox2.Font = font; richTextBox2.AppendText($"Font={richTextBox2.Font.Name}"); richTextBox2.SelectAll(); richTextBox2.SelectionFont = richTextBox1.Font; richTextBox2.Select(int.MaxValue, 0); if(!IsFontInstalled("smiley")) { Process.Start("explorer.exe", path); } \/\/ Now test to see if private font is available in the doc File.WriteAllText("output.rtf", richTextBox1.Rtf); Process.Start("explorer.exe", "output.rtf"); } PrivateFontCollection privateFontCollection = new PrivateFontCollection();<\/code><\/pre>
Regardless of whether or not it gets installed as a system font<\/em> the private font is in memory and can be shown to work properly in the RichTextBox<\/code> itself:<\/i>无论它是否作为系统字体安装,<\/em>私有字体都在内存中,并且可以显示在RichTextBox<\/code>本身中正常工作:<\/b><\/p>
![](/img/trans.png)
![](/img/trans.png)
Technically speaking, both the RTF spec<\/a> and the openxml<\/a> (for MS Word) support embedded fonts but I keep reading things that say that they tend to get stripped out if you're not<\/em> opening the RTF file in an MS Office<\/strong> product.<\/i>从技术上讲,
RTF 规范<\/a>和openxml<\/a> (用于 MS Word)都支持嵌入字体,但我一直在读一些文章,说如果您不在<\/em>MS Office<\/strong>产品中打开 RTF 文件,它们往往会被删除。<\/b> Being clearly off the deep end with the topic by now, I made a Word doc, embedded the smiley.ttf<\/strong> font using the Save options in MS Word, exported it to RTF, and then tested it by uninstalling<\/em> the font in the Windows Personalization settings.<\/i>到目前为止,我已经清楚地脱离了这个主题,我制作了一个 Word 文档,使用 MS Word 中的保存选项嵌入了smiley.ttf<\/strong>字体,将其导出为 RTF,然后通过在 Windows 个性化设置中卸载<\/em>字体来测试它.<\/b> Even though I can clearly see the font embed when I inspect the RTF text of the document IT DID NOT WORK when I tried it.<\/i>即使我在检查文档的 RTF 文本时可以清楚地看到嵌入的字体,但在我尝试它时它没有工作。<\/b> So, IMO I wouldn't recommend embedding the font and would use one of the above strategies to install it on the deployed device instead.<\/i>因此,IMO 我不建议嵌入字体,而是使用上述策略之一将其安装在已部署的设备上。<\/b><\/p>"]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.