好的,我正在解决在文本框中嵌入 LCD 类型 True Type 字体的问题。至于一些背景,如果我将字体安装到我的系统上,我可以显示 lcd 字体,然后将其加载为文本框的字体类型,效果很好。但是,它不能作为应用程序中的嵌入字体。我正在使用 Visual Basic 中的 Windows 窗体应用程序,来自 Windows 7 机器上的 Microsoft Visual Studio 2010。
在将字体存储为资源文件并将属性设置为嵌入资源之后,我使用内存中的私有字体集合尝试了以下代码。
Imports System.Drawing.Text
Imports System.Runtime.InteropServices
Module CustomFont
'PRIVATE FONT COLLECTION TO HOLD THE DYNAMIC FONT
Private _pfc As PrivateFontCollection = Nothing
Public ReadOnly Property GetInstance(ByVal Size As Single, _
ByVal style As FontStyle) As Font
Get
'IF THIS IS THE FIRST TIME GETTING AN INSTANCE
'LOAD THE FONT FROM RESOURCES
If _pfc Is Nothing Then LoadFont()
'RETURN A NEW FONT OBJECT BASED ON THE SIZE AND STYLE PASSED IN
Return New Font(_pfc.Families(0), Size, style)
End Get
End Property
Private Sub LoadFont()
Try
'INIT THE FONT COLLECTION
_pfc = New PrivateFontCollection
'LOAD MEMORY POINTER FOR FONT RESOURCE
Dim fontMemPointer As IntPtr = _
Marshal.AllocCoTaskMem( _
My.Resources.DIGITALDREAMNARROW.Length)
'COPY THE DATA TO THE MEMORY LOCATION
Marshal.Copy(My.Resources.DIGITALDREAMNARROW, _
0, fontMemPointer, _
My.Resources.DIGITALDREAMNARROW.Length)
'LOAD THE MEMORY FONT INTO THE PRIVATE FONT COLLECTION
_pfc.AddMemoryFont(fontMemPointer, _
My.Resources.DIGITALDREAMNARROW.Length)
'FREE UNSAFE MEMORY
Marshal.FreeCoTaskMem(fontMemPointer)
Catch ex As Exception
'ERROR LOADING FONT. HANDLE EXCEPTION HERE
End Try
End Sub
End Module
此代码的问题在于您应该将控件的 UseCompatibleTextRendering 属性启用为 true。如果在标签或按钮文本上使用此模块,则效果很好。但是,对于文本框,没有 UseCompatibleTextRendering 属性。
我开始明白文本框使用 GDI 渲染,而其他文本控件使用 GDI+(我可能已经切换了那些,所以不要引用我的话,我只记得它们是不同的)。
我发现一些较旧的代码片段尝试使用 Windows 中 gdi32.dll 文件中的 AddFontMemResourceEX 函数,有些人声称它可以在文本框中使用。所以我创建了以下课程。
Imports System
Imports System.Drawing.Text
Imports System.IO
Imports System.Reflection
Public Class GetLCDFont
Private Declare Auto Function AddFontMemResourceEX Lib "gdi32.dll" _
(ByVal pbFont As Integer, ByVal cbFont As Integer, _
ByVal pdv As Integer, ByRef pcFonts As Integer) As IntPtr
Public Shared Function GetFont(ByVal fontName As String) As FontFamily
Dim exeCurrent As [Assembly] = [Assembly].GetExecutingAssembly()
Dim nameSpc As String = exeCurrent.GetName().Name.ToString()
Dim fontCollection As New PrivateFontCollection
Dim loadStream As Stream = exeCurrent.GetManifestResourceStream( _
nameSpc + "." + fontName)
Dim byteBuffer(CType(loadStream.Length, Integer)) As Byte
loadStream.Read(byteBuffer, 0, Int(CType(loadStream.Length, Integer)))
Dim fontPtr As IntPtr = Runtime.InteropServices.Marshal.AllocHGlobal( _
Runtime.InteropServices.Marshal.SizeOf(GetType(Byte)) * _
byteBuffer.Length)
Runtime.InteropServices.Marshal.Copy(byteBuffer, 0, fontPtr, byteBuffer.Length)
fontCollection.AddMemoryFont(fontPtr, byteBuffer.Length)
Dim pcFonts As Int32 = 1
AddFontMemResourceEX(fontPtr, byteBuffer.Length, 0, pcFonts)
Runtime.InteropServices.Marshal.FreeHGlobal(fontPtr)
Return fontCollection.Families(0)
End Function
Public Sub New()
End Sub
Protected Overrides Sub Finalize()
MyBase.Finalize()
End Sub
End Class
然而,当调用这个类时,我得到一个 InvalidOperationException 未处理。错误是无法在 DLL 'gdi32.dll' 中找到一个名为 'AddFontMemResourceEX' 的条目。
希望有人可以帮助我告诉我哪里出了问题,或者指出一个方向,以帮助我在文本框中嵌入字体以与 Windows 窗体应用程序一起使用。
MSDN 中引用的大多数示例都指向如何在使用 WPF 应用程序时打包字体。
谢谢你。