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 に答える