嵌入字体导致崩溃 [英] Embedded Font Causes a Crash

查看:24
本文介绍了嵌入字体导致崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆