Ошибка PInvoking Функция - PullRequest
       37

Ошибка PInvoking Функция

1 голос
/ 07 июня 2011

У меня есть следующий код как часть моего контроля. Функция SetReaderMode создает структуру и вызывает описанную здесь функцию, http://msdn.microsoft.com/en-us/library/bb775599(VS.85).aspx

Когда я запускаю этот код, я получаю сообщение об ошибке

Попытка чтения или записи в защищенную память. Это часто указывает на то, что другая память повреждена.

Я не уверен, в чем проблема. Что я делаю не так?

        <DllImport("Comctl32.dll", EntryPoint:="#383", _
         CallingConvention:=CallingConvention.StdCall)> _
    Private Shared Sub DoReaderMode(prmi As READERMODEINFO)

    End Sub

    <StructLayout(LayoutKind.Sequential)>
    Private Structure READERMODEINFO
        Dim cbSize As UInt32
        Dim hwnd As IntPtr
        Dim fFlags As UInt32
        Dim prc As IntPtr
        Dim pfnScroll As ReaderScrollCallbackDelegate
        Dim fFlags2 As TranslateDispatchCallbackDelegate
        Dim lParam As IntPtr
    End Structure

    Private Sub SetReaderMode()

        Dim Info As New READERMODEINFO
        Info.hwnd = Me.Handle
        Info.fFlags = 0
        Info.prc = IntPtr.Zero
        Info.pfnScroll = New ReaderScrollCallbackDelegate(AddressOf ReaderScrollCallback)
        Info.fFlags2 = New TranslateDispatchCallbackDelegate(AddressOf TranslateDispatchCallback)
        Info.lParam = IntPtr.Zero
        Info.cbSize = Marshal.SizeOf(Info)

        DoReaderMode(Info)

    End Sub


    Private Delegate Function ReaderScrollCallbackDelegate(ByVal prmi As READERMODEINFO, dx As Integer, dy As Integer) As Boolean
    Private Delegate Function TranslateDispatchCallbackDelegate(lpmsg As IntPtr) As Boolean

    <AllowReversePInvokeCalls()>
    Private Function TranslateDispatchCallback(lpmsg As IntPtr) As Boolean
        Return True
    End Function

    <AllowReversePInvokeCalls()>
    Private Function ReaderScrollCallback(ByVal prmi As READERMODEINFO, dx As Int32, dy As Int32) As Boolean
        Return True
    End Function

Ответы [ 2 ]

1 голос
/ 08 июня 2011

Я понял это.После более подробного изучения документации я добавил ByRef к определению DoReaderMode и определению ReaderScrollCallback, поскольку аргументы определены как указатели на структуры, а не просто на структуры.Я также добавил другой код для передачи прямоугольника в структуру ReaderModeInfo.

Ниже приведен рабочий код.Интересно, что в документации говорится, что вы нажимаете, чтобы выйти из ReaderMode, однако при тестировании похоже, что вы должны удерживать кнопку и отпустить, чтобы выйти.

    <DllImport("Comctl32.dll", EntryPoint:="#383", _
         CallingConvention:=CallingConvention.StdCall)> _
    Private Shared Sub DoReaderMode(ByRef prmi As READERMODEINFO)

    End Sub

    <StructLayout(LayoutKind.Sequential)>
    Private Structure READERMODEINFO
        Dim cbSize As UInt32
        Dim hwnd As IntPtr
        Dim fFlags As UInt32
        Dim prc As IntPtr
        Dim pfnScroll As ReaderScrollCallbackDelegate
        Dim fFlags2 As TranslateDispatchCallbackDelegate
        Dim lParam As IntPtr
    End Structure


    Private Sub SetReaderMode()

        Dim SetReaderModeInfo As READERMODEINFO

        Dim rect As New Interop.RECT(Me.Width / 2 - 20, Me.Height / 2 - 20, Me.Width / 2 + 20, Me.Height / 2 + 20)

        Dim pnt As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(rect))
        Marshal.StructureToPtr(rect, pnt, True)

        SetReaderModeInfo = New READERMODEINFO
        SetReaderModeInfo.hwnd = Me.Handle
        SetReaderModeInfo.fFlags = 1
        SetReaderModeInfo.prc = pnt
        SetReaderModeInfo.pfnScroll = New ReaderScrollCallbackDelegate(AddressOf ReaderScrollCallback)
        SetReaderModeInfo.fFlags2 = New TranslateDispatchCallbackDelegate(AddressOf TranslateDispatchCallback)
        SetReaderModeInfo.lParam = IntPtr.Zero
        SetReaderModeInfo.cbSize = Marshal.SizeOf(SetReaderModeInfo)

        DoReaderMode(SetReaderModeInfo)

        Marshal.FreeHGlobal(pnt)

    End Sub

    Private Delegate Function ReaderScrollCallbackDelegate(ByRef prmi As READERMODEINFO, dx As Integer, dy As Integer) As Boolean

    Private Delegate Function TranslateDispatchCallbackDelegate(ByRef lpmsg As Interop.MSG) As Boolean

    Private Function TranslateDispatchCallback(ByRef lpmsg As Interop.MSG) As Boolean
        Return False
    End Function

    Private Function ReaderScrollCallback(ByRef prmi As READERMODEINFO, dx As Int32, dy As Int32) As Boolean
        Return True
    End Function
1 голос
/ 07 июня 2011

Легко взломать.Если предположить, что обратный вызов верен с точки зрения соглашения подписи / вызова, проблема может заключаться в том, что сборщик мусора собирает Info в конце функции SetReaderMode, адрес обратного вызова становится недействительным.Поэтому попробуйте объявить Info как переменную-член.Если ошибка остается, в сигнатуре обратного вызова что-то не так, но, как я уже сказал, не так просто увидеть ошибку с первого взгляда.

...