VB 5/6-Tipp 0560: Mausrad Subclassen
von Christof Rueß
Beschreibung
Dieser Tipp zeigt, wie man mit Visual Basic ein Mausrad Subclassen kann, um es für eigene Zwecke, wie zB Spiele verwenden zu können. Im hier gezeigten Beispiel wird das Mausrad lediglich dazu genutzt, eine Progressbar zu verändern.
Schwierigkeitsgrad: | Verwendete API-Aufrufe: CallNextHookEx, CallWindowProcA (CallWindowProc), GetCurrentThreadId, SetWindowLongA (SetWindowLong), SetWindowsHookExA (SetWindowsHookEx), UnhookWindowsHookEx | Download: |
'Dieser Quellcode stammt von http://www.activevb.de 'und kann frei verwendet werden. Für eventuelle Schäden 'wird nicht gehaftet. 'Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum. 'Ansonsten viel Spaß und Erfolg mit diesem Source! '------------- Anfang Projektdatei Projekt1.vbp ------------- ' Die Komponente 'Microsoft Windows Common Controls 6.0 (SP6) (MsComCtl.ocx)' wird benötigt. '--------- Anfang Formular "Form1" alias Form1.frm --------- ' Steuerelement: Fortschrittsanzeige "ProgressBar1" ' Steuerelement: Beschriftungsfeld "Label1" Private Sub Form_Load() Init Me End Sub Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) Ende End Sub Private Sub Form_Unload(Cancel As Integer) Ende End Sub '---------- Ende Formular "Form1" alias Form1.frm ---------- '--------- Anfang Modul "Module1" alias Module1.bas --------- Public Declare Function SetWindowsHookEx Lib "user32" Alias _ "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, _ ByVal hmod As Long, ByVal dwThreadId As Long) As Long Public Declare Function GetCurrentThreadId Lib "kernel32" () As Long Public Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, _ ByVal nCode As Long, ByVal wParam As Long, lParam As Any) As Long Public Declare Function UnhookWindowsHookEx Lib "user32" _ (ByVal hHook As Long) As Long Public 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 Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _ (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) _ As Long Private Type POINTAPI X As Long Y As Long End Type Private Type MOUSEHOOKSTRUCT pt As POINTAPI hWnd As Long wHitTestCode As Long dwExtraInfo As Long End Type Private Const WM_MOUSEWHEEL = &H20A Private Const WM_MBUTTONUP = &H208 Private Const WM_MBUTTONDOWN = &H207 Private Const WM_MBUTTONDBLCLK = &H209 Private Const WM_LBUTTONDOWN = &H201 Private Const WM_LBUTTONUP = &H202 Private Const MK_LBUTTON = &H1 Private Const MK_MBUTTON = &H10 Private Const MK_RBUTTON = &H2 Public Const WH_MOUSE = 7 Private Const WHEEL_DELTA = 120 Public Const GWL_WNDPROC = -4 Dim hook As Long Dim nKeys As Long, Delta As Long, XPos As Long, YPos As Long Dim OriginalWindowProc As Long Public Enum mButtons LBUTTON = &H1 MBUTTON = &H10 RBUTTON = &H2 End Enum Public Function MouseProc(ByVal nCode As Long, ByVal wParam As Long, _ lParam As MOUSEHOOKSTRUCT) As Long Select Case nCode Case Is < 0 MouseProc = CallNextHookEx(hook, nCode, wParam, lParam) Case 0 If lParam.hWnd = Form1.hWnd Then Select Case wParam Case WM_MBUTTONDOWN MouseWheelDown lParam.pt.X, lParam.pt.Y Debug.Print "Button down:" & lParam.pt.X & "," & lParam.pt.Y Case WM_MBUTTONUP MouseWheelUp lParam.pt.X, lParam.pt.Y Debug.Print "Button up:" & lParam.pt.X & "," & lParam.pt.Y End Select End If End Select End Function Public Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, _ ByVal wParam As Long, ByVal lParam As Long) _ As Long Select Case uMsg Case WM_MOUSEWHEEL nKeys = wParam And 65535 Delta = wParam / 65536 / WHEEL_DELTA XPos = lParam And 65535 YPos = lParam / 65536 MouseWheelRotation Delta, nKeys, XPos, YPos, hWnd Debug.Print "Mousewheel at (" & XPos & "," & YPos & ") Delta:" & _ Delta & " Keys:" & nKeys End Select WindowProc = CallWindowProc(OriginalWindowProc, hWnd, uMsg, wParam, _ lParam) End Function 'Nicht vergessen: Ende() ausführen!!! Public Function Init(Form As Form) hook = SetWindowsHookEx(WH_MOUSE, AddressOf MouseProc, 0, _ GetCurrentThreadId) OriginalWindowProc = SetWindowLong(Form.hWnd, GWL_WNDPROC, _ AddressOf WindowProc) End Function Public Function Ende() UnhookWindowsHookEx hook SetWindowLong Form1.hWnd, GWL_WNDPROC, OriginalWindowProc End Function Public Function MouseWheelRotation(Richtung As Long, Buttons As mButtons, _ X As Long, Y As Long, hWnd As Long) 'Hier die eigene Auswertung rein If Form1.ProgressBar1.Value < Form1.ProgressBar1.Max And _ Richtung = 1 Then Form1.ProgressBar1.Value = Form1.ProgressBar1.Value + Richtung ElseIf Form1.ProgressBar1.Value > Form1.ProgressBar1.Min And _ Richtung = -1 Then Form1.ProgressBar1.Value = Form1.ProgressBar1.Value + Richtung End If End Function Public Function MouseWheelUp(X As Long, Y As Long) Form1.Label1.Caption = "WheelButtonUp" End Function Public Function MouseWheelDown(X As Long, Y As Long) Form1.Label1.Caption = "WheelButtonDown" End Function '---------- Ende Modul "Module1" alias Module1.bas ---------- '-------------- Ende Projektdatei Projekt1.vbp --------------
Tipp-Kompatibilität:
Windows/VB-Version | Win32s | Win95 | Win98 | WinME | WinNT4 | Win2000 | WinXP |
VB4 | |||||||
VB5 | |||||||
VB6 |
Ihre Meinung
Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.
Archivierte Nutzerkommentare
Klicken Sie diesen Text an, wenn Sie die 7 archivierten Kommentare ansehen möchten.
Diese stammen noch von der Zeit, als es noch keine direkte Forenunterstützung für Fragen und Kommentare zu einzelnen Artikeln gab.
Aus Gründen der Vollständigkeit können Sie sich die ausgeblendeten Kommentare zu diesem Artikel aber gerne weiterhin ansehen.
Kommentar von Eckhart Wörner am 15.07.2003 um 13:15
Eine andere Möglichkeit ist es, wenn man nicht direkt subclasst, sondern ein anderes Programm dies tun lässt. Dadurch arbeitet man zwar nicht ganz so effizient, aber dafür sicherer.
Ein Beispiel wäre http://www.vbsmart.com/library/smartsubclass/smartsubclass.htm
Kommentar von Eckhart Wörner am 15.07.2003 um 13:11
An alle, die sich über das Problem mit dem Absturz beklagen:
Wenn man das Mausrad subclasst, greift man sehr stark in die Low-Level-Programmierung ein. Wird nun das Programm beendet, ohne dass dieser Eingriff in das System gelöscht wird, dann kommen an das Programm, das diese Aufrufe angefordert hat, immer noch Ereignisse. Da in der IDE das Programm aber immer noch VB6.EXE heißt (das Programm und die Entwicklungsumgebung sind ein Thread), bekommt nun die VB6 IDE diese Ereignisse zu spüren. Da die IDE jedoch mit so etwas nicht umgehen kann, stürzt sie ab.
Kommentar von Emanuel am 08.05.2003 um 17:26
Hab den Tipp auch ausprobiert. Wenn man nichts verändert, funktioniert es noch. Wenn man das Programm dann aber wieder beenden will, bekomme ich eine Fehlermeldung und VB hängt sich komplett weg. Sobald man am Projekt etwas verändert, z.B. zwei Listboxen drauftut, wie Florian schreibt, funktioniert der Tipp nicht mehr. Ich hatte versicht, diesen Tipp in ein eigenes Programm einzubauen, aber auch das hat nur Fehler und VB-Abstürze bewirkt. Ich wollte eigentlich nur eine Scrollbar damit steuern. Naja, vielleicht kann das ja nochmal jemand überarbeiten, der sich damit auskennt.
Kommentar von Florian Ackermann am 07.05.2003 um 23:10
Ich hatte gerade 2 Listboxen eingefügt
aber dann ging das mausrad nicht mehr d.h. die progressbar änderte sich nicht mehr.
kann mir das einer erklären?
MFG
Florian
Kommentar von Florian Rittmeier am 25.04.2003 um 14:26
Man kann das nicht Stop-Button-Unempfindlich machen.
Subclassing ist einfach eine Technik, die auch Risiken hat.
MfG Florian
Kommentar von Jonathan am 27.12.2002 um 21:34
Wie kann ich das Stop-Button-Unempfindlich machen???
Kommentar von Christof Rueß am 13.12.2002 um 23:55
Der code stammt auch von mir.
Beide sollten eigentlich ein Wettbewerbbeitrag gewesen sein. Egal, was solls