嵌入字体导致崩溃 [英] Embedded Font Causes a Crash
问题描述
我有一个 WinForm 应用程序.我正在使用嵌入资源中的自定义字体.
它起初工作,但随后导致程序在一段时间后崩溃.
以下面的代码为例,如果我不断调整表单的大小,强迫它不断地重绘自己,它会在几秒钟内崩溃.我得到的消息是Error in 'Form1_Paint()'".对象当前正在别处使用.
'.
我究竟做错了什么?我怎样才能避免这种情况?
我从这里获得了字体.
谢谢.
I have a WinForm app. I am using a custom font that is in my embedded resources.
It works at first, but then causes the program to crash after a while.
Using the following code as an example, if I keep resizing the form, forcing it to constantly redraw itself, it will crash within a few seconds. The message I get is 'Error in 'Form1_Paint()'. Object is currently in use elsewhere.
'.
What am I doing wrong? How can I avoid this?
I got the font from here.
Thanks.
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
推荐答案
Marshal.FreeCoTaskMem(FontPtr)
PrivateFontCollection 的 MSDN 文档对此过于晦涩.但是您需要保持所添加字体的内存有效,直到您不能再使用该字体.或者换句话说,AddMemoryFont() 不会不复制字体.因此,当您的程序尝试访问字体数据并被另一个非托管内存分配覆盖时,它会因神秘的 GDI+ 错误而失败.
The MSDN documentation for PrivateFontCollection is too obtuse about this. But you need to keep the memory for the added font valid until you can no longer use the font. Or to put it another way, AddMemoryFont() does not make a copy of the font. So your program will fall over with a mysterious GDI+ error when it tries to access the font data and it got overwritten by another unmanaged memory allocation.
将 FreeCoTaskMem() 调用移动到 FormClosed 事件处理程序.或者,如果关闭表单也会终止您的程序,请不要打扰.
Move the FreeCoTaskMem() call to a FormClosed event handler. Or don't bother if closing the form also terminates your program.
这篇关于嵌入字体导致崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!