2

OK 私は LCD タイプの True Type フォントをテキスト ボックスに埋め込む問題に取り組んでいます。いくつかの背景については、システムにフォントをインストールし、それをテキスト ボックスのフォント タイプとしてロードすると、lcd フォントを表示することができ、うまく機能します。ただし、アプリケーションの埋め込みフォントとしては機能しません。Windows 7 ボックスの Microsoft Visual Studio 2010 から、Visual Basic で Windows フォーム アプリケーションを使用しています。

フォントをリソース ファイルとして保存し、リソースを埋め込むようにプロパティを設定した後、メモリからプライベート フォント コレクションを使用して次のコードを試しました。

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 アプリケーションを使用するときにフォントをパッケージ化する方法を示しています。

ありがとうございました。

4

2 に答える 2

0

上記のコードをラベルに使用してきましたが、テキスト ボックスを試したことはありません。

OnPaint はテキストをレンダリングしないため、Textbox から継承するカスタム テキスト ボックス クラスを作成し、WndProc メソッドをオーバーライドすることができます。

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
于 2013-02-24T01:42:31.367 に答える
0

クリーンではありませんが、インストーラーを使用してフォントをアプリケーション ディレクトリに配置し、次のコマンドを使用して PrivateFontCollection にロードできます。

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

Microsoft がこれを別の方法で扱う理由はわかりませんが、TextBoxes と ComboBoxes は、UseCompatibleTextRendering プロパティがなくてもカスタム フォントを使用するようになりました。

于 2015-05-19T19:19:49.940 に答える