Access或VB为任何控件添加鼠标滚轮事件
Access及VB 的有些控件不支持鼠标滚轮,或滚轮的行为不是你需要的,默认的滚轮可能是上下移动,本程序实现捕获任何控件的鼠标滚轮事件。
程序运行后,当窗口的焦点控件是水平滚动条时,滚动鼠标滚轮,滚动条的滑块即可上下移动。
当窗口焦点控件是按钮时,滚动鼠标滚轮,可改变窗口的大小。
单击一下图片框,滚动鼠标滚轮可改变图片框的大小。
滚动鼠标滚轮要实现的效果,可通过修改模块的“MousScroll”过程实现。
调试注意:本程序是通过拦截窗口消息捕获鼠标滚轮事件的。VB 在处理窗口消息回调函数的时候,运行时如果设置断点,很容易造成程序无响应异常终止。因此,修改代码后应及时保存。
如果是Access, 可以在控件的获得焦点事件(GetFocus)绑定钩子,在失去焦点事件(LostFocus)中释放钩子
以下代码摘自网络:
'''本程序包含一个窗体 Form1 和一个模块 Module1,在 VB6 和 WinXP 下调试通过。
'以下是窗体 Form1 代码 =====================================
'在窗体添加以下控件,不用设置任何属性:
' 按钮1个:Command1
' 图片框1个:Picture1
' 水平滚动条1个:HScroll1
' 垂直滚动条1个:VScroll1
Private Sub Form_Load()
Me.Caption = "捕获鼠标滚轮事件"
Command1.Caption = "新窗口"
VScroll1.Max = 100
HScroll1.Max = 100
Picture1.Picture = Me.Icon
End Sub
Private Sub Form_Activate()
StartProc Me '开始拦截窗口消息
End Sub
Private Sub Form_Unload(Cancel As Integer)
StopProc '停止拦截窗口消息
End Sub
Private Sub Command1_Click()
Dim nForm As New Form1
nForm.Show
End Sub
以下是模块 Module1 代码 =====================================
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Const GWL_WNDPROC = -4
Private Const WM_MOUSEWHEEL = &H20A
Dim moProc As Long, moForm As Form
'自定滚轮事件
Private Sub MousScroll(ByVal nVal As Single)
'获取鼠标滚轮事件后,要做的事情
'nVal=1 表示鼠标滚轮向下滚,nVal=-1 表示鼠标滚轮向上滚
Dim Kj As Object, nType As String, W As Single, H As Single
If moForm Is Nothing Then Exit Sub
On Error Resume Next
Set Kj = moForm.ActiveControl
nType = TypeName(Kj)
Select Case nType
Case "HScrollBar", "VScrollBar" '焦点控件是滚动条
nVal = Kj.Value + nVal * 3
If nVal > Kj.Max Then nVal = Kj.Max
If nVal < Kj.Min Then nVal = Kj.Min
Kj.Value = nVal
Case "PictureBox" '焦点控件是图片框,改变控件大小,每次 3 个像素
W = Kj.Container.ScaleX(Kj.Width, Kj.Container.ScaleMode, 3) + nVal * 3
H = Kj.Container.ScaleY(Kj.Height, Kj.Container.ScaleMode, 3) + nVal * 3
If W < 4 Or H < 4 Then Exit Sub
W = Kj.Container.ScaleX(W, 3, Kj.Container.ScaleMode)
H = Kj.Container.ScaleY(H, 3, Kj.Container.ScaleMode)
Kj.Move Kj.Left, Kj.Top, W, H
Case Else '其他情况:改变窗体大小,每次 3 个像素
W = moForm.Width + nVal * Screen.TwipsPerPixelX * 3
H = moForm.Height + nVal * Screen.TwipsPerPixelY * 3
If W < 90 Or H < 90 Then Exit Sub
moForm.Move moForm.Left, moForm.Top, W, H
End Select
End Sub
Private Function WinProc(ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'窗口消息回调函数
If wMsg = WM_MOUSEWHEEL Then
If wParam = -7864320 Then MousScroll 1 '鼠标滚轮向下滚
If wParam = 7864320 Then MousScroll -1 '鼠标滚轮向上滚
End If
WinProc = CallWindowProc(moProc, hWnd, wMsg, wParam, lParam)
End Function
Public Sub StartProc(nForm As Form)
'开始拦截窗口消息
Dim nWnd As Long
On Error GoTo Err1
nWnd = nForm.hWnd
Call StopProc '开始前,先还原
On Error GoTo 0
moProc = GetWindowLong(nWnd, GWL_WNDPROC)
SetWindowLong nWnd, GWL_WNDPROC, AddressOf WinProc
Set moForm = nForm
Exit Sub
Err1:
MsgBox Err.Description
End Sub
Public Sub StopProc()
'停止拦截窗口消息:还原窗口消息地址
If moProc = 0 Or (moForm Is Nothing) Then Exit Sub
SetWindowLong moForm.hWnd, GWL_WNDPROC, moProc
moProc = 0
End Sub
其它相关可参考的代码:
VB 获得鼠标滚轮的事件
'窗体代码
Private Sub Form_Load()
HookMouse Me.hwnd
End Sub
Private Sub Form_Unload(Cancel As Integer)
UnHookMouse Me.hwnd
End Sub
'模块代码
'***********************************************************
'mMouseWheel
'鼠标滚轮的事件检测
'***********************************************************
Option Explicit
Private Declare Function CallWindowProc Lib "User32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function SetWindowLong Lib "User32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Const GWL_WNDPROC = -4
Private Const WM_MOUSEWHEEL = &H20A
Global lpPrevWndProcA As Long
Public bMouseFlag As Boolean '鼠标事件激活标志
Public Sub HookMouse(ByVal hwnd As Long)
lpPrevWndProcA = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub
Public Sub UnHookMouse(ByVal hwnd As Long)
SetWindowLong hwnd, GWL_WNDPROC, lpPrevWndProcA
End Sub
Private Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Select Case uMsg
Case WM_MOUSEWHEEL '滚动
Dim wzDelta, wKeys As Integer
'wzDelta传递滚轮滚动的快慢,该值小于零表示滚轮向后滚动(朝用户方向),
'大于零表示滚轮向前滚动(朝显示器方向)
wzDelta = HIWORD(wParam)
'wKeys指出是否有CTRL=8、SHIFT=4、鼠标键(左=2、中=16、右=2、附加)按下,允许复合
wKeys = LOWORD(wParam)
'--------------------------------------------------
If wzDelta < 0 Then '朝用户方向
Form1.Cls
Form1.Print "朝用户方向滚"
Else '朝显示器方向
Form1.Cls
Form1.Print "朝显示器方向"
End If
'--------------------------------------------------
Case Else
WindowProc = CallWindowProc(lpPrevWndProcA, hw, uMsg, wParam, lParam)
End Select
End Function
Private Function HIWORD(LongIn As Long) As Integer
HIWORD = (LongIn And &HFFFF0000) \ &H10000 '取出32位值的高16位
End Function
Private Function LOWORD(LongIn As Long) As Integer
LOWORD = LongIn And &HFFFF& '取出32位值的低16位
End Function