0

我正在尝试获取已拖放到我的表单上的元文件中的评论数据,但是,此代码会生成错误:

附加信息:运行时遇到致命错误。错误地址位于线程 0x2080 上的 0xeb556610。错误代码为 0xc0000005。此错误可能是 CLR 中的错​​误或用户代码的不安全或不可验证部分中的错误。此错误的常见来源包括 COM 互操作或 PInvoke 的用户封送错误,这可能会损坏堆栈。

我见过的每个代码示例都谈到从元文件而不是元文件本身获取图像。错误发生在 DragDrop 处理程序中的“Dim mf = Metafile”上,它永远不会到达枚举代码。

Private Sub Form1_DragEnter(sender As Object, e As System.Windows.Forms.DragEventArgs) Handles Me.DragEnter
    If e.Data.GetDataPresent(DataFormats.EnhancedMetafile, False) Then
        e.Effect = DragDropEffects.Copy
    End If
End Sub

Private Sub Form1_DragDrop(sender As Object, e As System.Windows.Forms.DragEventArgs) Handles Me.DragDrop
    If e.Data.GetDataPresent(DataFormats.EnhancedMetafile, False) Then
        Dim mf As Metafile = e.Data.GetData(DataFormats.EnhancedMetafile, False)
        Me.CreateGraphics().EnumerateMetafile(mf, New Point(0, 0), New Graphics.EnumerateMetafileProc(AddressOf MetafileCallback))
    End If
End Sub

Private Function MetafileCallback(ByVal recordType As EmfPlusRecordType, ByVal flags As Integer, ByVal dataSize As Integer, ByVal data As IntPtr, ByVal callbackData As PlayRecordCallback) As Boolean
    If recordType = EmfPlusRecordType.Comment Then
        Debug.WriteLine("Got comment")
    End If
End Function
4

1 回答 1

1

简短的回答:您不能拖放元文件。你就是不能。但是,您可以将它放在剪贴板上,然后使用 User32.dll 魔法将其保存到那里。

下面是 get 和 put 代码:

Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices

Public Class ClipboardMetafileHelper
    <DllImport("user32.dll", EntryPoint:="OpenClipboard", _
       SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function OpenClipboard(ByVal hWnd As IntPtr) As Boolean
    End Function
    <DllImport("user32.dll", EntryPoint:="IsClipboardFormatAvailable", _
       SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function IsClipboardFormatAvailable(ByVal uFormat As Integer) As Boolean
    End Function
    <DllImport("user32.dll", EntryPoint:="EmptyClipboard", _
       SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function EmptyClipboard() As Boolean
    End Function
    <DllImport("user32.dll", EntryPoint:="SetClipboardData", _
       SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function SetClipboardData(ByVal uFormat As Integer, ByVal hWnd As IntPtr) As IntPtr
    End Function
    <DllImport("user32.dll", EntryPoint:="GetClipboardData", _
       SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function GetClipboardData(ByVal uFormat As Integer) As IntPtr
    End Function
    <DllImport("user32.dll", EntryPoint:="CloseClipboard", _
       SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function CloseClipboard() As Boolean
    End Function
    <DllImport("gdi32.dll", EntryPoint:="CopyEnhMetaFileA", _
       SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function CopyEnhMetaFile(ByVal hemfSrc As IntPtr, ByVal hNULL As IntPtr) As IntPtr
    End Function
    <DllImport("gdi32.dll", EntryPoint:="DeleteEnhMetaFile", _
       SetLastError:=True, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function DeleteEnhMetaFile(ByVal hemfSrc As IntPtr) As Boolean
    End Function

    Private Const CF_ENHMETAFILE As Integer = 14

    ' Metafile mf is set to a state that is not valid inside this function.
    Public Shared Function PutEnhMetafileOnClipboard(ByVal hWnd As IntPtr, ByVal mf As Metafile) As Boolean
        Dim bResult As Boolean = False
        Dim hEMF, hEMF2 As IntPtr

        hEMF = mf.GetHenhmetafile() ' invalidates mf
        If Not hEMF.Equals(New IntPtr(0)) Then
            hEMF2 = CopyEnhMetaFile(hEMF, New IntPtr(0))
            If Not hEMF2.Equals(New IntPtr(0)) Then
                If OpenClipboard(hWnd) Then
                    If EmptyClipboard() Then
                        Dim hRes As IntPtr
                        hRes = SetClipboardData(CF_ENHMETAFILE, hEMF2)
                        bResult = hRes.Equals(hEMF2)
                        CloseClipboard()
                    End If
                End If
            End If
            DeleteEnhMetaFile(hEMF)
        End If

        Return bResult
    End Function

    Public Shared Function GetEnhMetafileOffClipboard(ByVal hWnd As IntPtr, ByRef mf As Metafile) As Boolean
        Dim bResult As Boolean = False
        Dim hEMF As IntPtr

        If OpenClipboard(hWnd) Then
            If IsClipboardFormatAvailable(CF_ENHMETAFILE) Then
                hEMF = GetClipboardData(CF_ENHMETAFILE)
                If Not hEMF.Equals(New IntPtr(0)) Then
                    mf = New Metafile(hEMF, True)
                    bResult = True
                End If
            End If
            CloseClipboard()
        End If

        Return bResult
    End Function

End Class
于 2015-02-07T08:18:20.507 回答