Vb.net 在Visual Basic 2010中嵌入自定义字体fot文本框

Vb.net 在Visual Basic 2010中嵌入自定义字体fot文本框,vb.net,visual-studio-2010,fonts,textbox,gdi,Vb.net,Visual Studio 2010,Fonts,Textbox,Gdi,好的,我正在解决一个问题:如何在文本框中嵌入LCD类型的true type字体。至于一些背景,我可以得到液晶字体显示,如果我安装到我的系统中的字体,然后加载它作为文本框的字体类型,它的作品很棒。但是,它不能作为应用程序中的嵌入式字体使用。我正在使用Visual Basic中的Windows窗体应用程序,该应用程序来自Microsoft Visual Studio 2010中的Windows 7框 在将字体存储为资源文件并将属性设置为嵌入资源后,我尝试使用内存中的私有字体集合执行以下代码 Impo

好的,我正在解决一个问题:如何在文本框中嵌入LCD类型的true type字体。至于一些背景,我可以得到液晶字体显示,如果我安装到我的系统中的字体,然后加载它作为文本框的字体类型,它的作品很棒。但是,它不能作为应用程序中的嵌入式字体使用。我正在使用Visual Basic中的Windows窗体应用程序,该应用程序来自Microsoft Visual Studio 2010中的Windows 7框

在将字体存储为资源文件并将属性设置为嵌入资源后,我尝试使用内存中的私有字体集合执行以下代码

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
但是,调用此类时,我得到一个未处理的InvalidOperatioException。该错误无法在DLL“gdi32.DLL”中找到名为“AddFontMemResourceEX”的指向项

希望有人能帮助我,告诉我哪里出了问题,或者给我指出一个方向,帮助我在文本框中嵌入字体,以便与Windows窗体应用程序一起使用

MSDN中引用的大多数示例都指向如何在使用WPF应用程序时打包字体


谢谢。

我一直在使用上述标签代码,但从未尝试使用文本框

您可以创建一个从Textbox继承的自定义文本框类,然后重写WndProc方法,因为OnPaint不会呈现文本

Public Class CustomTextBox
  Inherits TextBox

  Public Const WM_NCPAINT As Integer = &H85

  <DllImport("User32.dll")> _
  Public Shared Function GetWindowDC(ByVal hWnd As IntPtr) As IntPtr
  End Function

  <DllImport("user32.dll")> _
  Private Shared Function ReleaseDC(ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As Boolean
  End Function

  Protected Overrides Sub WndProc(ByRef m As Message)
    MyBase.WndProc(m)

    If m.Msg = WM_NCPAINT Then
      Dim hDC As IntPtr = GetWindowDC(m.HWnd)
      Using g As Graphics = Graphics.FromHdc(hDC)
        g.DrawString(Me.Text, GetInstance(10, FontStyle.Bold), New SolidBrush(Me.ForeColor), Me.ClientRectangle)
      End Using
      ReleaseDC(m.HWnd, hDC)
    End If

  End Sub
End Class
公共类CustomTextBox
继承文本框
Public Const WM_NCPAINT为整数=&H85
_
公共共享函数GetWindowDC(ByVal hWnd作为IntPtr)作为IntPtr
端函数
_
私有共享函数ReleaseDC(ByVal hWnd作为IntPtr,ByVal hDC作为IntPtr)作为布尔值
端函数
受保护的覆盖子WndProc(ByRef m作为消息)
MyBase.WndProc(m)
如果m.Msg=WM\n则
Dim hDC As IntPtr=GetWindowDC(m.HWnd)
使用g作为Graphics=Graphics.FromHdc(hDC)
g、 DrawString(Me.Text、GetInstance(10、FontStyle.Bold)、新SolidBrush(Me.ForeColor)、Me.ClientRectangle)
终端使用
释放DC(m.HWnd,hDC)
如果结束
端接头
末级

虽然没有那么干净,但您可以使用安装程序将字体放在应用程序目录中,并使用以下方法将其加载到PrivateFontCollection中:

    For Each fontfile As String In System.IO.Directory.GetFiles(filepath & "\Fonts", "*.ttf")
        _pfc.AddFontFile(fontfile)
    Next fontfile

我不知道为什么微软会对此有所不同,但我的文本框和组合框现在使用我的自定义字体,即使它们没有可用的CompatibleTextRendering属性。

我尝试过这个,它主要是按照我(和原始海报)的要求来做的正在查找。我想你不知道如何消除这些行为:1.它在我将鼠标悬停在文本框上之前不会更新,2.它在文本框的中间和左边都有一个文本副本(我只希望它在中间)。