来自dragDrop的metafile getData会生成异常

时间:2014-12-12 19:35:36

标签: vb.net drag-and-drop metafile

我正在尝试将一个已拖放到我的表单上的元文件中的注释数据,但是,此代码会生成错误:

  

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

我见过的每个代码示例都是关于从Metafile而不是元文件本身获取图像的。错误发生在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

1 个答案:

答案 0 :(得分: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