2013-05-04 2 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

Смежные вопросы