C#使用外部字体、嵌入字体到程序资源中(Winform)及字体的版权问题

简介: 应用程序能够使用一个好的字体,是用户界面很重要的一部分,但是很多字体如果系统没有安装,则需要额外引入,这就涉及到极其重要的字体版权问题,及额外字体的使用和安装。最好的方式应该是将字体嵌入到程序中...

引入

我们先看一下按钮显示的字体的例子。如下,新建一个名为EmbedFont的winform项目,给定三个Button,设置基本样式:

button1.FlatStyle = button2.FlatStyle = button3.FlatStyle = FlatStyle.Flat;
button1.FlatAppearance.BorderSize = button2.FlatAppearance.BorderSize = button3.FlatAppearance.BorderSize = 0;
button1.ForeColor = button2.ForeColor = button3.ForeColor = Color.White;

button1.BackColor = Color.MediumPurple;
button2.BackColor = Color.CadetBlue;
button3.BackColor = Color.OrangeRed;

显示如下:

基本效果不错,但是字体是默认的“宋体, 9pt”,总体感觉差点,好看的字体有很多,但是如果系统没有安装也无法使用【需要额外单独安装字体】

下面就简要介绍下字体,以及如何嵌入到Winform的程序资源中,免除需要安装的麻烦。

常见字体及版权

字体版权

注意:很多字体是有版权的,需要付费才能使用,否则直接使用很容易收到版权投诉,最出名的莫过于微软雅黑(Microsoft Yahei),其商业版权归属北大方正。

微软雅黑是美国微软公司委托北京北大方正电子有限公司设计的一款全面支持ClearType技术的字体。字体设计上属于无衬线字体和黑体。

微软雅黑的版权分为两个部分:个人使用为目的的Windows系统的内嵌使用、屏幕输出和打印;以商业发布为目的的微软雅黑版权,由北大方正保留。

关于字体使用侵权的问题,详细介绍可参考 设计师别担心,微软雅黑这样使用不侵权。直接引用系统自带的字体用于显示不属于侵权,但是直接使用或嵌入使用、海报艺术设计上直接使用等,又是商业用途,需要授权。

一些常见的免费字体中,属于明星级别的应该就是思源系列:思源黑体、思源宋体。

此外免费字体还有:

思源柔黑体、思源真黑体、

装甲明朝、源界明朝、花园明朝【明朝系列】

方正黑体、方正书宋、方正仿宋、方正楷体【四种方正免费字体】

源样明体、源流明体、源云明体【源明体系列】

以及站酷系列的很多字体等

推荐参考 48款无版权可商用字体送你,别再用微软雅黑了!那些你日思夜想的无版权字体,我都为你打包好了(超全合集)

而Windows中常见宋体、黑体、楷体、仿宋体等也是有版权的,在计算机软件著作权上需要商业授权,具体可参考 Windows自带的宋体、黑体、楷体、仿宋体等能免费商用吗?

总之使用上还是要注意。

一些查询字体的工具也提供了是否可免费使用的提示,比如

360查字体:https://fonts.safe.360.cn/

常见中文字体对应的英文名称

思源黑体 ---- Source Han Sans CN
思源宋体 ---- Source Han Serif SC

宋体 ---- SimSun
黑体 ---- SimHei
微软雅黑 ---- Microsoft Yahei
微软正黑体 ---- Microsoft JhengHei
楷体 ---- KaiTi
新宋体 ---- NSimSun
仿宋 ---- FangSong
隶书 ---- LiSu
华文行楷 ---- STXingkai

更多参考 CSS font-family中文字体对应的英文名称一览表css font-family常用的黑体宋体等字体中英文对照表

引用系统已安装字体

下面直接引用系统中的微软雅黑、黑体、隶书、华文行楷等,对比看看和默认的宋体效果:

//// 黑体
//button1.Font = button2.Font = button3.Font = new Font("SimHei", 11f, FontStyle.Regular);

//// 微软雅黑
//button1.Font = button2.Font = button3.Font = new Font("Microsoft Yahei", 11f, FontStyle.Regular);

//// 隶书
//button1.Font = button2.Font = button3.Font = new Font("LiSu", 13f, FontStyle.Regular);

//// 华文行楷
button1.Font = button2.Font = button3.Font = new Font("STXingkai", 13f, FontStyle.Regular);

C#使用外部字体和嵌入字体文件到程序

C#程序使用外部字体文件

上面是直接应用系统的字体,但是有些字体系统并不自带,或没有安装,比如思源系列字体。一个比较好的处理方式是将字体嵌入到程序中,随程序一起被携带使用。

借助私有字体集合类PrivateFontCollection,可以实现引用外部提供的字体,在程序中设定和使用。由于字体文件较大,通常引用一个需要的即可。比如从网上下载的一个思源黑体SourceHanSansCN-Regular.otf就有8M(如果要嵌入多个,真的伤不起...)

复制多个字体文件到生成的程序文件目录中(Debug或Release),同时定义一个字体路径的变量,程序运行时将其添加到PrivateFontCollection对象,后面就可以直接引用了。

PrivateFontCollection pfc = new PrivateFontCollection(); // using System.Drawing.Text;

/// <summary>
/// 添加第三方字体
/// </summary>
void AddPrivateFont()
{
    // 字体路径
    string[] fontNames = { "沐瑶软笔手写体.ttf", "SourceHanSansCN-Regular.otf", "SourceHanSansSC-Heavy.otf" };
    for (int i = 0; i < fontNames.Length; i++)
    {
        pfc.AddFontFile(fontNames[i]);
    }
}

加载并使用字体文件

AddPrivateFont();

// 使用字体文件提供的字体
button1.Font = new Font(pfc.Families[2], 12f);
button2.Font = new Font(pfc.Families[1], 12f);
button3.Font = new Font(pfc.Families[0], 15f);

嵌入字体到程序资源中(使用内存字体)

  1. 通过项目的Resources.resx资源添加字体文件为资源文件,实现字体文件嵌入到程序中。

(或者项目属性->资源)

  1. Resources资源引用的是二进制文件,可以实现直接添加到PrivateFontCollection对象中。
/// <summary>
/// 添加第三方字体
/// </summary>
void AddPrivateFont()
{
    var fontData1 = Properties.Resources.沐瑶软笔手写体;
    var fontData2 = Properties.Resources.SourceHanSansCN_Regular;
    var fontData3 = Properties.Resources.SourceHanSansSC_Heavy;
    unsafe  // 属性设置,生成中 允许不安全代码
    {
        // 将字体添加到PrivateFontCollection
        fixed (byte* pFontData = fontData1)
        {
            pfc.AddMemoryFont((System.IntPtr)pFontData, fontData1.Length);
        }
        fixed (byte* pFontData = fontData2)
        {
            pfc.AddMemoryFont((System.IntPtr)pFontData, fontData2.Length);
        }
        fixed (byte* pFontData = fontData3)
        {
            pfc.AddMemoryFont((System.IntPtr)pFontData, fontData3.Length);
        }
    }
}
  1. 项目属性中允许不安全代码:

  1. 使用 SetCompatibleTextRenderingDefault(true)UseCompatibleTextRendering=true 设置控件启用GDI+渲染使用内存字体(否则字体不生效)
AddPrivateFont();

// 使用内存字体,需要设置 SetCompatibleTextRenderingDefault(true) 或 UseCompatibleTextRendering=true
button1.UseCompatibleTextRendering = button2.UseCompatibleTextRendering = button3.UseCompatibleTextRendering = true;
// 使用字体文件提供的字体
button1.Font = new Font(pfc.Families[2], 12f);
button2.Font = new Font(pfc.Families[1], 12f);
button3.Font = new Font(pfc.Families[0], 15f);
To use the memory font, text on a control must be rendered with GDI+. Use the SetCompatibleTextRenderingDefault method, passing true, to set GDI+ rendering on the application, or on individual controls by setting the control's UseCompatibleTextRendering property to true. Some controls cannot be rendered with GDI+.

效果如下,可以看到,内存字体和直接从字体文件添加的方式有不少区别,有些小瑕疵,尤其是第二个按钮字体,整体偏上,无法正确居中。

嵌入的资源字体文件(资源清单,使用内存字体)

  1. 可以通过直接在项目中添加->现有项,添加字体文件到项目中,然后修改资源文件属性“生成操作”为“嵌入的资源”(BuildActionEnbedded Resource)。

  1. 然后通过Assembly的GetManifestResourceStream(sourceName)方法加载嵌入的资源文件,并添加到PrivateFontCollection
注意:资源必须是包含完整命名空间的名称,否则无法加载到。
/// <summary>
/// 添加第三方字体
/// </summary>
void AddPrivateFont()
{
   var fontName = "沐瑶软笔手写体.ttf";
   // 加载字体
   Assembly assembly = Assembly.GetExecutingAssembly();

   string projectName = assembly.GetName().Name;
   // 加载程序资源
   using (Stream stream = assembly.GetManifestResourceStream($"{projectName}.{fontName}"))
   {
       if (stream == null)
       {
           throw new Exception("资源文件不存在");
       }
       byte[] fontData = new byte[stream.Length];

       stream.Read(fontData, 0, (int)stream.Length);
       stream.Close();

       unsafe  // 属性设置,生成中 允许不安全代码
       {
           // 将字体添加到PrivateFontCollection
           fixed (byte* pFontData = fontData)
           {
               pfc.AddMemoryFont((System.IntPtr)pFontData, fontData.Length);
           }
       }
   }
}
  1. 使用内存字体
button3.UseCompatibleTextRendering = true;
button3.Font = new Font(pfc.Families[0], 15f);

效果:

Graphics(GDI+)直接使用内存字体

直接在控件上应用内存字体,必须启用兼容渲染(Compatible)。而如果直接使用GDI+的Graphics对象绘制文字时,就可以直接使用内存字体。

比如在窗体的Paint事件处理中绘制内存字体的文字:

/// <summary>
/// 窗体的Paint事件方法
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Paint(object sender, PaintEventArgs e)
{
   Graphics g = e.Graphics;
   Font font = new Font(pfc.Families[0], 20);
   g.DrawString("我是使用内存字体写的文字内容", font, new SolidBrush(Color.PaleVioletRed), 200, 300);
}

Windows中的字体文件及字体安装

Windows中的字体文件位于 C:\Windows\Fonts 中。

而安装字体文件的方法也很简单:

  • 一是直接复制字体文件到系统字体文件夹中
  • 二是右键在菜单中选择“安装”

参考

相关文章
|
1月前
|
C#
C# WinForm发送Email邮件
C# WinForm发送Email邮件
C# WinForm发送Email邮件
|
1月前
|
C#
C# DEV 关于设置gridview 指定单元格字体为红色
C# DEV 关于设置gridview 指定单元格字体为红色
|
3月前
|
SQL 数据库连接 应用服务中间件
C#WinForm基础编程(三)
C#WinForm基础编程
82 0
|
3月前
C#WinForm基础编程(二)
C#WinForm基础编程
61 0
|
3月前
|
C# 数据安全/隐私保护
C#WinForm基础编程(一)
C#WinForm基础编程
63 0
|
4月前
|
C# 开发者
C# 9.0中的模块初始化器:程序启动的新控制点
【1月更文挑战第14天】本文介绍了C# 9.0中引入的新特性——模块初始化器(Module initializers)。模块初始化器允许开发者在程序集加载时执行特定代码,为类型初始化提供了更细粒度的控制。文章详细阐述了模块初始化器的语法、用途以及与传统类型初始化器的区别,并通过示例代码展示了如何在实际项目中应用这一新特性。
|
3天前
|
SQL 存储 Oracle
C#利用IDbCommand实现通用数据库脚本执行程序
C#利用IDbCommand实现通用数据库脚本执行程序
|
14天前
|
前端开发 Java C#
C#程序启动后乱码(通过idea启动)
C#程序启动后乱码(通过idea启动)
18 0
|
1月前
|
JavaScript C#
C#winForm程序与html JS交互调用
C#winForm程序与html JS交互调用
|
2月前
|
Java C# 开发工具
第一个C#程序
第一个C#程序
12 0