Does the API have a function to tell if the mouse button is clicked, Like GetCursorPos()?
Printable View
Does the API have a function to tell if the mouse button is clicked, Like GetCursorPos()?
Not exactly -> when a mouse button is pressed, or released, or moved, Windows sends messages to the window under the cursor....
To detect ANY mouse button event in ANY window, you need to monitor those messages, which is possible with a global Hook procedure..
Dr Memory :cool:
How would you do that?
don't you wish they made a GetAsyncMouseState? Is there
something that would work atleast vaguely like that?
The way a global hook works is a bit like sub-classing - you call an API routine SetWindowsHookEx, passing it the address of your mouse event procedure. You can then monitor the system-wide mouse traffic, and detect events of interest, like WM_LBUTTONDOWN, WM_RBUTTONDOWN, etc..
It's possible to determine the position of the mouse when the event occurred, the window under the cursor at the time, and even what part of the window (like the title bar, control menu, window frame, etc).
Unfortunately, a VB program can only set local hooks - i.e. hooks for threads created by the prgram itself.
Only a DLL can set a system-wide mouse hook procedure. So you need a DLL to do the SetWindowsHookEx call for you. Such a DLL is provided by 3rd-party tools like DesaWare's SpyWorks.
It's not hard to make one of your own, but I don't have Visual C so I can't help....
Dr Memory :cool:
You saying I have to crate an some kind of event handler like in a C++ API app. and put it in a DLL.
No. You create a hook. Serge posted a mouse hook example, to trap right clicks. You'd want to change it to trap ANY click.
VB code here:
http://www.vbforums.com/showthread.p...tWindowsHookEx
Here's an example of a hook procedure.
Module:
Create a form with 2 buttons and a list box - label the first button "Set" and the 2nd button "Release". Now paste in this code:Code:Option Explicit
Private 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
Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private MouseHookHandle As Long
Public Sub SetMouseHook()
Const WH_MOUSE = 7&
MouseHookHandle = SetWindowsHookEx(WH_MOUSE, AddressOf MyMouseHandler, App.hInstance, App.ThreadID)
End Sub
Public Sub ReleaseMouseHook()
If MouseHookHandle = 0 Then Exit Sub
UnhookWindowsHookEx MouseHookHandle
MouseHookHandle = 0
End Sub
Public Function MyMouseHandler(ByVal HookID As Long, ByVal MsgCode As Long, ByVal pMouseHookInfo As Long) As Long
Const WM_LBUTTONDOWN = &H201& ' MouseDown - Left button
Const WM_MBUTTONDOWN = &H207& ' Middle
Const WM_RBUTTONDOWN = &H204& ' Right
Const HC_ACTION = 0&
If HookID <> HC_ACTION Then GoTo PassItOn
Select Case MsgCode
Case WM_LBUTTONDOWN
Form1.List1.AddItem "Left Click "
Case WM_RBUTTONDOWN
Form1.List1.AddItem "Right Click "
End Select
PassItOn:
'
' allow mouse event to be passed on and processed normally
'
MyMouseHandler = CallNextHookEx(MouseHookHandle, HookID, MsgCode, pMouseHookInfo)
Exit Function
End Function
When you run it, and press the "Set" button - any left or right click on the form itself will cause the hook procedure to register the event in the list box.Code:Private Sub Command1_Click()
SetMouseHook
Command1.Enabled = False
Command2.Enabled = True
End Sub
Private Sub Command2_Click()
ReleaseMouseHook
Command2.Enabled = False
Command1.Enabled = True
End Sub
Private Sub Form_Load()
Command1.Enabled = True
Command2.Enabled = False
End Sub
Private Sub Form_Unload(Cancel As Integer)
ReleaseMouseHook
End Sub
BUT, click on another window in another application and it won't register. The reason is that the call to SetWindowsHookEx says we only want mouse events in our own application passed through to our hook procedure. That's a LOCAL hook.
To set a GLOBAL hook, the last parameter must be 0, but if you look up the MSDN entry for SetWindowsHookEx, it tells you that the procedure making the call can only request a global hook if it's calling from a DLL.
Add-ins like SpyWorks give you such a DLL, and give you a control that you can use in your VB program which has a method to establish the hook, and Events that the DLL will trigger so you can get notification of the mouse events.
Dr Memory :cool:
GetAsyncKeyState doesn't just only get KeyBoard. by using these 3 constants:Quote:
Originally posted by macai
don't you wish they made a GetAsyncMouseState? Is there
something that would work atleast vaguely like that?
Private Const VK_LBUTTON = &H1
Private Const VK_RBUTTON = &H2
Private Const VK_MBUTTON = &H4
you could check for the mouse buttons w/o hooking.
Hmmm, doesn't that only work if your own app has the focus?
wait let me rephrase that. it will work whenever and whereever. not only your own app focus.
Well, you're absolutely right serves me right for believing MSDN!
Well spotted, BuggyProgrammer!
So our friend just needs to run a timer, like this:
Sorry to mislead! mea culpa, mea culpa, etc.....Code:Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
Private Const VK_LBUTTON = &H1
Private Const VK_RBUTTON = &H2
'
' following is only needed if you want to identify the window
' in which the mouse is being clicked
'
Private Type POINTAPI
X As Long
Y As Long
End Type
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Declare Function WindowFromPoint Lib "user32" (ByVal xPoint As Long, ByVal yPoint As Long) As Long
Private Sub Timer1_Timer()
Static lastvalL%, lastvalR%
Dim thisvalL%, thisvalR%
Dim cpoint As POINTAPI
thisvalL = GetAsyncKeyState(VK_LBUTTON)
If thisvalL <> lastvalL Then
lastvalL = thisvalL
If thisvalL <> 0 Then
GetCursorPos cpoint
List1.AddItem "Left Click - " & Hex(WindowFromPoint(cpoint.X, cpoint.Y))
End If
End If
thisvalR = GetAsyncKeyState(VK_RBUTTON)
If thisvalR <> lastvalR Then
lastvalR = thisvalR
If thisvalR <> 0 Then
GetCursorPos cpoint
List1.AddItem "Right Click - " & Hex(WindowFromPoint(cpoint.X, cpoint.Y))
End If
End If
End Sub
Dr Memory :eek:
but it won't work at the same precision as the hook. if you hold the button down it will keep adding the item.
It's probably good enough for our "client"'s purposes, with any luck..
Also, the example I posted looks at the bit that tells you if there's been any change since the last call, so you don't get continuous repetition if you hold the button down....
Dr Memory :cool: