2011-06-07 80 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