2013-05-04 57 views
1

我有一個WinForm應用程序。我正在使用我的嵌入式資源中的自定義字體。
它首先起作用,但隨後導致程序在一段時間後崩潰。
以下面的代碼爲例,如果我不斷調整窗體大小,迫使它不斷重繪,它會在幾秒鐘內崩潰。我收到的消息是'Error in 'Form1_Paint()'. Object is currently in use elsewhere.'。
我在做什麼錯?我怎樣才能避免這種情況?
我從here.得到了字體
謝謝。嵌入字體導致崩潰

Imports System.Drawing.Text 
Imports System.Runtime.InteropServices 

Public Class Form1 
    Friend Harabara As Font 

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 
     LoadFonts() 
    End Sub 

    Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint 
     Try 
      e.Graphics.DrawString("This was drawn using the custom font 'Harabara'", Harabara, Brushes.Lime, 10.0F, 10.0F) 
     Catch ex As Exception 
      MsgBox("Error in Form1_Paint()'" & vbCrLf & ex.Message) 
     End Try 
    End Sub 

    Public Sub LoadFonts() 
     Try 
      Harabara = GetFontInstance(My.Resources.HarabaraHand, 24.0F, FontStyle.Italic) 
     Catch ex As Exception 
      MsgBox("Error in 'LoadFonts()'" & vbCrLf & ex.Message) 
     End Try 
    End Sub 

    Private Function GetFontInstance(ByVal data() As Byte, ByVal Size As Single, ByVal Style As FontStyle) As Font 
     Dim result As Font 
     Try 
      Dim pfc = New PrivateFontCollection 
      'LOAD MEMORY POINTER FOR FONT RESOURCE 
      Dim FontPtr As System.IntPtr = Marshal.AllocCoTaskMem(data.Length) 
      'COPY THE DATA TO THE MEMORY LOCATION 
      Marshal.Copy(data, 0, FontPtr, data.Length) 
      'LOAD THE MEMORY FONT INTO THE PRIVATE FONT COLLECTION 
      pfc.AddMemoryFont(FontPtr, data.Length) 
      'FREE UNSAFE MEMORY 
      Marshal.FreeCoTaskMem(FontPtr) 

      result = New Font(pfc.Families(0), Size, Style) 
      pfc.Families(0).Dispose() 
      pfc.Dispose() 
     Catch ex As Exception 
      'ERROR LOADING FONT. HANDLE EXCEPTION HERE 
      MsgBox("Error in 'GetFontInstance()'" & vbCrLf & ex.Message) 
      result = New Font(FontFamily.GenericMonospace, 8) 
     End Try 
     Return result 
    End Function 
End Class 

回答

2
 Marshal.FreeCoTaskMem(FontPtr) 

MSDN文檔PrivateFontCollection是太遲鈍了這一點。但是你需要保持添加字體的內存有效,直到你不能再使用字體。或者換一種說法,AddMemoryFont()做而不是製作字體的副本。因此,當您的程序嘗試訪問字體數據並被另一個非託管內存分配覆蓋時,您的程序將會遇到神祕的GDI +錯誤。

將FreeCoTaskMem()調用移動到FormClosed事件處理程序。或者,如果關閉表單也會終止您的程序,請不要打擾。

+0

謝謝,它的工作。我將'FontPtr'和'pfc'移出函數並放入'Form1'類,並在應用程序的整個生命週期中保留它們。沒有更多的崩潰。 – mcu 2013-05-04 14:41:10