2011-06-07 76 views
1

我有以下代码作为我的控件的一部分。 SetReaderMode函数创建结构和调用函数这里解释,http://msdn.microsoft.com/en-us/library/bb775599(VS.85).aspx错误PInvoking函数

当我运行此代码,我得到的错误

试图读取或写入保护内存。这通常表明其他内存已损坏。

我不确定这个问题可能是什么。我究竟做错了什么?

 <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 

回答

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 
+0

您在ReaderScrollCallback中如何使它像在excel中的readermode一样工作? – 2011-09-23 09:54:30

1

不是一件容易的事情。假设根据签名/调用惯例的回调是正确的,一个问题可能是由于carbage收集器在函数SetReaderMode的末尾收集Info,回调地址变得无效。所以尝试将Info声明为一个成员变量。如果错误仍然是回调签名有问题,但正如我所说,不容易看到错误一目了然。

+0

我把它改成了一个成员变量,但结果相同。我不确定回调签名会出现什么问题,但我对这种东西不是很熟悉。 – Kratz 2011-06-07 19:07:30

+0

我知道它总是很困难:如果对结构进行处理,请尝试在www.pinvoke.net上看到。 – 2011-06-07 19:24:22

+0

这是签名不正确,因为它证明。尽管如此,pinvoke.net没有什么。我将结构作为局部变量离开,在测试之后,DoReaderMode函数实际上并没有返回,直到它完成。 – Kratz 2011-06-08 13:17:54