1

我有以下代码作为我的控制的一部分。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
4

2 回答 2

1

不是一个容易破解的坚果。假设回调在签名/调用约定方面是正确的,那么问题可能是由于碳收集器在函数 SetReaderMode 的末尾收集 Info,因此回调地址变得无效。所以尝试将 Info 声明为成员变量。如果错误仍然存​​在,回调签名有问题,但正如我所说,一目了然地看到错误并不是那么容易。

于 2011-06-07T18:48:40.580 回答
1

我已经想通了。在更仔细地查看文档之后,我在DoReaderMode定义和ReaderScrollCallback定义中添加了 ByRef,因为参数定义为指向结构的指针,而不仅仅是结构。我还添加了一些其他代码来传递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
于 2011-06-08T13:15:58.777 回答