如何在 C# 中的 winforms 应用程序中快速轻松地嵌入字体
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/556147/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to quickly and easily embed fonts in winforms app in C#
提问by Niklas Winde
This is probably noob territory but what the heck:
这可能是菜鸟的领域,但到底是什么:
I want to embed fonts in my winforms application so that I don't have to worry about them being installed on the machine. I've searched a bit on the MSDN site and found a few hints about using native Windows API calls, for instance Michael Caplans (sp?) tutorial linked to by Scott Hanselman. Now, do I really have to go through all that trouble? Can't I just use the resource part of my app?
我想在我的 winforms 应用程序中嵌入字体,这样我就不必担心它们会安装在机器上。我在 MSDN 站点上进行了一些搜索,发现了一些有关使用本机 Windows API 调用的提示,例如由 Scott Hanselman 链接的 Michael Caplans (sp?) 教程。现在,我真的必须经历所有这些麻烦吗?我不能只使用我的应用程序的资源部分吗?
If not I'll probably go the installing route. In that case, can I do that programmatically? By just copying the font file to the Windows\Fonts folder?
如果没有,我可能会走安装路线。在这种情况下,我可以以编程方式做到这一点吗?只是将字体文件复制到 Windows\Fonts 文件夹?
Edit: I am aware of licencing issues, thanks for the concern though.
编辑:我知道许可问题,但感谢您的关注。
回答by Richard
Can't I just use the resource part of my app?
我不能只使用我的应用程序的资源部分吗?
Yes, but need to be native resources rather than .NET resources (i.e. using rc.exe, the native resource compiler).
可以,但需要是本机资源而不是 .NET 资源(即使用本机资源编译器 rc.exe)。
回答by David Maron
// specify embedded resource name
string resource = "embedded_font.PAGAP___.TTF";
// receive resource stream
Stream fontStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resource);
// create an unsafe memory block for the font data
System.IntPtr data = Marshal.AllocCoTaskMem((int)fontStream.Length);
// create a buffer to read in to
byte[] fontdata = new byte[fontStream.Length];
// read the font data from the resource
fontStream.Read(fontdata, 0, (int)fontStream.Length);
// copy the bytes to the unsafe memory block
Marshal.Copy(fontdata, 0, data, (int)fontStream.Length);
// pass the font to the font collection
private_fonts.AddMemoryFont(data, (int)fontStream.Length);
// close the resource stream
fontStream.Close();
// free up the unsafe memory
Marshal.FreeCoTaskMem(data);
回答by knighter
This is what worked for me in VS 2013, without having to use an unsafe block.
这就是在 VS 2013 中对我有用的方法,而不必使用不安全的块。
Embed the resource
嵌入资源
- Double-click Resources.resx, and in the toolbar for the designer click Add Resource/Add Existing File and select your .ttf file
- In your solution explorer, right-click your .ttf file (now in a Resources folder) and go to Properties. Set the Build Action to "Embedded Resource"
- 双击 Resources.resx,然后在设计器的工具栏中单击 Add Resource/Add Existing File 并选择您的 .ttf 文件
- 在您的解决方案资源管理器中,右键单击您的 .ttf 文件(现在位于资源文件夹中)并转到属性。将构建操作设置为“嵌入式资源”
Load the font into memory
将字体加载到内存中
Add
using System.Drawing.Text;
to your Form1.cs fileAdd code above and inside your default constructor to create the font in memory (without using "unsafe" as other examples have shown). Below is my entire Form1.cs:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Reflection; using System.Drawing.Text; namespace WindowsFormsApplication1 { public partial class Form1 : Form { [System.Runtime.InteropServices.DllImport("gdi32.dll")] private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont, IntPtr pdv, [System.Runtime.InteropServices.In] ref uint pcFonts); private PrivateFontCollection fonts = new PrivateFontCollection(); Font myFont; public Form1() { InitializeComponent(); byte[] fontData = Properties.Resources.MyFontName; IntPtr fontPtr = System.Runtime.InteropServices.Marshal.AllocCoTaskMem(fontData.Length); System.Runtime.InteropServices.Marshal.Copy(fontData, 0, fontPtr, fontData.Length); uint dummy = 0; fonts.AddMemoryFont(fontPtr, Properties.Resources.MyFontName.Length); AddFontMemResourceEx(fontPtr, (uint)Properties.Resources.MyFontName.Length, IntPtr.Zero, ref dummy); System.Runtime.InteropServices.Marshal.FreeCoTaskMem(fontPtr); myFont = new Font(fonts.Families[0], 16.0F); } } }
添加
using System.Drawing.Text;
到您的 Form1.cs 文件在默认构造函数上方和内部添加代码以在内存中创建字体(不使用“不安全”,如其他示例所示)。下面是我的整个 Form1.cs:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Reflection; using System.Drawing.Text; namespace WindowsFormsApplication1 { public partial class Form1 : Form { [System.Runtime.InteropServices.DllImport("gdi32.dll")] private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont, IntPtr pdv, [System.Runtime.InteropServices.In] ref uint pcFonts); private PrivateFontCollection fonts = new PrivateFontCollection(); Font myFont; public Form1() { InitializeComponent(); byte[] fontData = Properties.Resources.MyFontName; IntPtr fontPtr = System.Runtime.InteropServices.Marshal.AllocCoTaskMem(fontData.Length); System.Runtime.InteropServices.Marshal.Copy(fontData, 0, fontPtr, fontData.Length); uint dummy = 0; fonts.AddMemoryFont(fontPtr, Properties.Resources.MyFontName.Length); AddFontMemResourceEx(fontPtr, (uint)Properties.Resources.MyFontName.Length, IntPtr.Zero, ref dummy); System.Runtime.InteropServices.Marshal.FreeCoTaskMem(fontPtr); myFont = new Font(fonts.Families[0], 16.0F); } } }
Use your font
使用你的字体
Add a label to your main form, and add a load event to set the font in Form1.cs:
private void Form1_Load(object sender, EventArgs e) { label1.Font = myFont; }
给你的主窗体添加一个标签,并添加一个加载事件来设置 Form1.cs 中的字体:
private void Form1_Load(object sender, EventArgs e) { label1.Font = myFont; }
回答by Bitterblue
I dragged and dropped a randomly downloaded fontinto my resources and this worked. Uses a file though. I guess you can use this as well to install fonts ?
我将随机下载的字体拖放到我的资源中,这奏效了。虽然使用文件。我猜你也可以用它来安装字体?
public Form1()
{
string filename = @"C:\lady.gaga";
File.WriteAllBytes(filename, Resources.KBREINDEERGAMES);
PrivateFontCollection pfc = new PrivateFontCollection();
pfc.AddFontFile(filename);
Label label = new Label();
label.AutoSize = true;
label.Font = new Font(pfc.Families[0], 16);
label.Text = "hello world";
Controls.Add(label);
}