2013-02-23 62 views
2

好的我正在处理一个问题,以便在文本框中嵌入LCD类型的真实类型字体。至于某些背景,如果我将字体安装到我的系统中,然后将其作为文本框的字体类型加载,并且它工作得很好,我可以获取显示的lcd字体。但是,它不能在应用程序中用作嵌入式字体。我在Windows 7中使用Windows窗体应用程序在Visual Basic中,从Microsoft Visual Studio 2010在Windows 7框中。在Visual Basic 2010中嵌入自定义字体fot文本框

我已经尝试使用内存中的专用字体集合以下代码后,将字体存储为资源文件和该属性设置为嵌入的资源。

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属性。

I已经明白了文本框使用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是未处理的。该错误是无法找到一个名为'AddFontMemResourceEX DLL'gdi32.dll'中的条目。

希望有人可以帮助我告诉我我错了什么,或者指出我的方向,可以帮助我在文本框中嵌入用于Windows窗体应用程序的字体。

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

谢谢。

回答

0

我已经使用上面的代码标签,但从来没有尝试过使用文本框。

您可以创建自定义文本框类继承自文本框,然后重写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 
+0

我试过了,它主要做我(和原始海报)正在寻找的东西。我不认为你会知道如何消除这些行为:1.它不会更新,直到我将鼠标悬停在文本框上,2.它在文本框的中间和左侧有一个文本副本(仅限我希望它在中心)。 – BigBobby 2015-05-19 19:16:39

0

虽然它不是干净的,你可以用你的安装程序把字体在你的应用程序目录,并使用它们加载到您的PrivateFontCollection:

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

我不知道为什么微软对待这不同,但我的TextBoxes和ComboBoxes现在使用我的自定义字体,即使它们没有UseCompatibleTextRendering属性。