- Public Class ContextMenuHelper
#Region "事件"
Public Event ButtonDbClick(ByVal SubControl As Control, ByVal e As MouseEventArgs)
Public Event ButtonClick(ByVal SubControl As Control, ByVal e As MouseEventArgs)
#End Region
Public Sub HookAllControls(ByVal ControlList As List(Of Control))
For Each ThisControl As Control In ControlList
If Not ThisControl.ContextMenu Is Nothing Then
Dim CustomMessageWindow As New CustomMessageWindow(ThisControl)
AddHandler CustomMessageWindow.ButtonDbClick, AddressOf ButtonDbClickPro
AddHandler CustomMessageWindow.ButtonClick, AddressOf ButtonClickPro
End If
Next
End Sub
Public Sub ButtonDbClickPro(ByVal SubControl As Control, ByVal e As MouseEventArgs)
RaiseEvent ButtonDbClick(SubControl, e)
End Sub
Public Sub ButtonClickPro(ByVal SubControl As Control, ByVal e As MouseEventArgs)
RaiseEvent ButtonClick(SubControl, e)
End Sub
End Class
- Public Class CustomMessageWindow : Implements IDisposable
#Region "API"
<DllImport("coredll.dll", CharSet:=CharSet.Unicode, SetLastError:=True)> _
Private Shared Function SetWindowLong(ByVal hWnd As IntPtr, ByVal nIndex As Integer, ByVal NewProc As Win32WndProc) As IntPtr
End Function
<DllImport("coredll.dll", CharSet:=CharSet.Unicode, SetLastError:=True)> _
Private Shared Function SetWindowLong(ByVal hWnd As IntPtr, ByVal nIndex As Integer, ByVal newProc As IntPtr) As IntPtr
End Function
<DllImport("coredll.dll", CharSet:=CharSet.Unicode, SetLastError:=True)> _
Private Shared Function CallWindowProc(ByVal lpPrevWndFunc As IntPtr, ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
End Function
#End Region
#Region "私有变量"
Private Delegate Function Win32WndProc(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
Private OldWndProc As IntPtr
Private NewWndProc As Win32WndProc = Nothing
Public SubControl As Control
#End Region
#Region "常量"
Private Const GWL_WNDPROC As Integer = -4
Private Const WM_LBUTTONDOWN As Integer = &H201
Private Const WM_LBUTTONDBLCLK As Integer = &H203
#End Region
#Region "事件"
Public Event ButtonDbClick(ByVal SubControl As Control, ByVal e As MouseEventArgs)
Public Event ButtonClick(ByVal SubControl As Control, ByVal e As MouseEventArgs)
#End Region
Public Sub New(ByVal NewSubControl As Control)
SubControl = NewSubControl
NewWndProc = New Win32WndProc(AddressOf MyWndProc)
OldWndProc = SetWindowLong(NewSubControl.Handle, GWL_WNDPROC, NewWndProc)
End Sub
Private Function MyWndProc(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
Select Case Msg
Case WM_LBUTTONDOWN
Dim X As Integer, Y As Integer
LoWord(X, Y, lParam)
RaiseEvent ButtonClick(SubControl, New MouseEventArgs(MouseButtons.Left, 0, X, Y, 0))
Return 1
Case WM_LBUTTONDBLCLK
Dim X As Integer, Y As Integer
LoWord(X, Y, lParam)
RaiseEvent ButtonDbClick(SubControl, New MouseEventArgs(MouseButtons.Left, 0, X, Y, 0))
Return 1
Case Else
Return CallWindowProc(OldWndProc, hWnd, Msg, wParam, lParam)
End Select
End Function
Public Sub LoWord(ByRef X As Integer, ByRef Y As Integer, ByVal lParam As Integer)
X = lParam And &HFFFF
Y = (lParam And &HFFFF0000) >> 16
End Sub
#Region " IDisposable Support "
Private disposedValue As Boolean = False
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
End If
SetWindowLong(SubControl.Handle, GWL_WNDPROC, OldWndProc)
End If
Me.disposedValue = True
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
为了完善wince5.0系统下控件右键菜单contextmenu的弹出问题,我制作了如上两个类
功能倒是实现了,但同时麻烦也出现了,问题是:经常弹出系统错误,并直接挂掉我的程序。具体原因小弟我已经弄明白:就是子类化中CallWindowProc函数回调窗口原消息处理函数中参数不严密导致的内存读写错误
这里想众大虾求救了请问:有在wince5.0下安全可靠的子类化方法或者现成的代码吗?