经过多次试验和错误,我终于让我的应用程序在开发机器以外的机器上使用自定义字体,但是,我不确定我已经开始使用的两种方法中的哪一种是首选的做事方式。
将字体作为资源嵌入并使用Assembly.GetManifestResourceStream()
将字体文件数据推送到非托管内存中并将其添加到PrivateFontCollection
使用中AddMemoryFont()
,如下所示:
(删除所有错误处理和多余代码)
Imports System.Runtime.InteropServices
Imports System.Drawing.Text
Public Class FormExample
Private ReadOnly pfc As New PrivateFontCollection
Private f As Font
Private ReadOnly Bytes() As Byte = GetFontData(Reflection.Assembly.GetExecutingAssembly, "MyFont.ttf")
Private ReadOnly fontPtr As IntPtr = Marshal.AllocCoTaskMem(Me.Bytes.Length)
Private Sub FormExample_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Marshal.Copy(Me.Bytes, 0, Me.fontPtr, Me.Bytes.Length)
Me.pfc.AddMemoryFont(Me.fontPtr, Me.Bytes.Length)
Me.f = New Font(Me.pfc.Families(0), 14, FontStyle.Regular)
'Iterate through forms controls and set font where valid
SetFormsCustomFont(Me, Me.f)
End Sub
Private Sub FormExample_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
Marshal.FreeCoTaskMem(Me.fontPtr)
Me.pfc.Dispose()
End Sub
Private Function GetFontData(Asm As Assembly, Name As String) As Byte()
Using Stream As Stream = Asm.GetManifestResourceStream(Name)
Dim Buffer() As Byte = New Byte(CInt(Stream.Length - 1)) {}
Stream.Read(Buffer, 0, CInt(Stream.Length))
Return Buffer
End Using
End Function
End Class
或者通过简单地将字体包含在应用程序中,而不是将其作为资源嵌入并使用PrivateFontCollection.AddFontFile()
:
Public Class FormExample2
Private ReadOnly pfc As New PrivateFontCollection
Private f As Font
Private Sub FormExample2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim fontFile As String = ".\Path\To\MyFont.ttf"
Me.pfc.AddFontFile(fontFile)
Me.f = New Font(Me.pfc.Families(0), 14)
'Iterate through forms controls and set font where valid
SetFormsCustomFont(Me, Me.f)
End Sub
Private Sub FormExample2_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed
Me.pfc.Dispose()
End Sub
End Class
在这两种方法中,字体集合都需要在表单的整个生命周期中保留,并且我必须重复代码并为应用程序中的每个表单设置字体对象,这样我就不会践踏非托管内存。
除了第二种方法允许用户访问您的字体文件这一事实之外,第一种方法还有其他好处吗?
或者,是否有另一种我不知道的首选方法?