該文章包括了VB中需要AddressOf操作符引用的API函數轉到VB.Net中的處理方法和委託被記憶體回收的處理方法。
VB:
API函數SetWindowLong在VB中定義如下:
Private Declare Function SetWindowLong& Lib "user32" Alias "SetWindowLongA" (ByVal hwnd&,ByVal nIndex&, ByVal dwNewLong&)
引用時是如下形式:
procOld=SetWindowLong(Me.hwnd, GWL_WNDPROC, AddressOf WindowProc)
其中AddressOf是取得WindowProc函數的地址。
VB.Net:
而轉到VB.Net中時,如果依舊將SetWindowLong聲明為如下形式:
Private Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" (ByVal hwnd As Integer, ByVal nIndex As Integer, ByVal dwNewLong As integer) As Integer
引用時procOld=SetWindowLong(Me.hwnd, GWL_WNDPROC, AddressOf WindowProc),則會出錯,錯誤為“AddressOf”運算式不能轉換為“Integer”,因為“Integer”不是委託類型。
此時就應用將SetWindowLong聲明為如下形式,
Private Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" (ByVal hwnd As Integer, ByVal nIndex As Integer, ByVal dwNewLong As DelegateWindowProc) As Integer
其中DelegateWindowPrco為要返回地址的函數的委託,如函數原型 Private Function WindowProc(ByVal hwnd As Integer, ByVal iMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer,則聲明其委託為Private Delegate Function DelegateWindowProc(ByVal hwnd As Integer, ByVal iMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
此時引用則採取如下形式:
Dim mysub As New DelegateWindowProc(AddressOf WindowProc)
procOld = SetWindowLong(m_Hwnd, GWL_WNDPROC, mysub)
這種方法,當你運行一段時間後,就會出現“委託被記憶體回收”的錯誤,導致程式崩潰,有兩種方法可以解決該問題,如下
第一種方法:
Dim mysub As New DelegateWindowProc(AddressOf WindowProc)
procOld = SetWindowLong(m_Hwnd, GWL_WNDPROC, mysub)
GCHandle.Alloc(mysub) ''為委託建立控制代碼,以免它被記憶體回收,導致出錯
第二種避免記憶體回收的辦法:
Dim mysub As New DelegateWindowProc(AddressOf WindowProc)
GC.Collect()
GC.WaitForPendingFinalizers()
procOld = SetWindowLong(m_Hwnd, GWL_WNDPROC, mysub)