Results 1 to 14 of 14

Thread: Mouse Button Click

  1. #1

    Thread Starter
    Addicted Member
    Join Date
    Jan 2001
    Location
    Little Rock, Ar
    Posts
    151

    Question Mouse Button Click

    Does the API have a function to tell if the mouse button is clicked, Like GetCursorPos()?

  2. #2
    Addicted Member MathImagics's Avatar
    Join Date
    Jun 2002
    Location
    Uki, NSW Australia
    Posts
    169
    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
    Last edited by MathImagics; Aug 9th, 2002 at 05:31 AM.
    "He's got a B.A. (in be-bop), a Ph.D. (in swing), he's a Master of Rhythm, he's the Rock'n'Roll king" ("The Rock'n'Roll Doctor", Lowell George)

    "If you push something hard enough, it will fall over" (Fudd's Third Law of Opposition)

  3. #3

    Thread Starter
    Addicted Member
    Join Date
    Jan 2001
    Location
    Little Rock, Ar
    Posts
    151
    How would you do that?

  4. #4
    Frenzied Member macai's Avatar
    Join Date
    Jul 2001
    Location
    Napanoch NY
    Posts
    1,228
    don't you wish they made a GetAsyncMouseState? Is there
    something that would work atleast vaguely like that?
    Luke

  5. #5
    Addicted Member MathImagics's Avatar
    Join Date
    Jun 2002
    Location
    Uki, NSW Australia
    Posts
    169
    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
    "He's got a B.A. (in be-bop), a Ph.D. (in swing), he's a Master of Rhythm, he's the Rock'n'Roll king" ("The Rock'n'Roll Doctor", Lowell George)

    "If you push something hard enough, it will fall over" (Fudd's Third Law of Opposition)

  6. #6

    Thread Starter
    Addicted Member
    Join Date
    Jan 2001
    Location
    Little Rock, Ar
    Posts
    151
    You saying I have to crate an some kind of event handler like in a C++ API app. and put it in a DLL.

  7. #7
    Frenzied Member
    Join Date
    Jul 2002
    Posts
    1,370
    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

  8. #8
    Addicted Member MathImagics's Avatar
    Join Date
    Jun 2002
    Location
    Uki, NSW Australia
    Posts
    169
    Here's an example of a hook procedure.

    Module:

    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
    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:
    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
    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.

    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
    Last edited by MathImagics; Aug 10th, 2002 at 06:46 PM.
    "He's got a B.A. (in be-bop), a Ph.D. (in swing), he's a Master of Rhythm, he's the Rock'n'Roll king" ("The Rock'n'Roll Doctor", Lowell George)

    "If you push something hard enough, it will fall over" (Fudd's Third Law of Opposition)

  9. #9
    The picture isn't missing BuggyProgrammer's Avatar
    Join Date
    Oct 2000
    Location
    Vancouver, Canada
    Posts
    5,217
    Originally posted by macai
    don't you wish they made a GetAsyncMouseState? Is there
    something that would work atleast vaguely like that?
    GetAsyncKeyState doesn't just only get KeyBoard. by using these 3 constants:

    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.
    Last edited by BuggyProgrammer; Aug 10th, 2002 at 07:24 PM.
    Remember, if someone's post was not helpful, you can always rate their post negatively .

  10. #10
    Addicted Member MathImagics's Avatar
    Join Date
    Jun 2002
    Location
    Uki, NSW Australia
    Posts
    169
    Hmmm, doesn't that only work if your own app has the focus?
    "He's got a B.A. (in be-bop), a Ph.D. (in swing), he's a Master of Rhythm, he's the Rock'n'Roll king" ("The Rock'n'Roll Doctor", Lowell George)

    "If you push something hard enough, it will fall over" (Fudd's Third Law of Opposition)

  11. #11
    The picture isn't missing BuggyProgrammer's Avatar
    Join Date
    Oct 2000
    Location
    Vancouver, Canada
    Posts
    5,217
    wait let me rephrase that. it will work whenever and whereever. not only your own app focus.
    Remember, if someone's post was not helpful, you can always rate their post negatively .

  12. #12
    Addicted Member MathImagics's Avatar
    Join Date
    Jun 2002
    Location
    Uki, NSW Australia
    Posts
    169
    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:

    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
    Sorry to mislead! mea culpa, mea culpa, etc.....

    Dr Memory
    Last edited by MathImagics; Aug 10th, 2002 at 07:57 PM.
    "He's got a B.A. (in be-bop), a Ph.D. (in swing), he's a Master of Rhythm, he's the Rock'n'Roll king" ("The Rock'n'Roll Doctor", Lowell George)

    "If you push something hard enough, it will fall over" (Fudd's Third Law of Opposition)

  13. #13
    The picture isn't missing BuggyProgrammer's Avatar
    Join Date
    Oct 2000
    Location
    Vancouver, Canada
    Posts
    5,217
    but it won't work at the same precision as the hook. if you hold the button down it will keep adding the item.
    Remember, if someone's post was not helpful, you can always rate their post negatively .

  14. #14
    Addicted Member MathImagics's Avatar
    Join Date
    Jun 2002
    Location
    Uki, NSW Australia
    Posts
    169
    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
    "He's got a B.A. (in be-bop), a Ph.D. (in swing), he's a Master of Rhythm, he's the Rock'n'Roll king" ("The Rock'n'Roll Doctor", Lowell George)

    "If you push something hard enough, it will fall over" (Fudd's Third Law of Opposition)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width