We help IT Professionals succeed at work.

Simple MouseMove Question

Last Modified: 2008-03-03
I have a form with a toolbar and a menubar.  The application displays different captions on a status bar when the mouse is over different toolbar buttons.  When the mouse goes below the toolbar I added code to the Form MouseMove event to return the status bar to default.  When the mouse goes above the toolbar I don't know where to add code for the menubar to return the status bar to default.  Any ideas?
Watch Question

Maybe you could calculate the position of your mouse.

if mousemove (x,y) = form.top - 20 then
 write your code here

Something like that

OK, In your tool bar MouseMove event Place the code that will show the changes in status bar. As soon as mouse leaves the toolbar , status will be default.

Or use an API to detect the mouse leaving your form:

see http://www.vb-world.net/demos/mouse/ for much information on this subject !



Catouch, I don't really want to do it that way because of different screen resolutions.  Is there any other way?

Marine, that's the way I have it now but when I leave the toolbar the status bar stays the same.  (The status bar is actually a SSPanel.)

I'll give you a better solution in a little later. For now you can do this. See if the focus left the toolbar if it did then change the status bar. Try using LostFocus , i am in a hurry i'll tlak to you later.


Marine, I can't find a LostFocus event for the toolbar.  Do you have a code sample?
Top Expert 2005

Use the SetCapture() API in the toolbar MouseMove event.  Then you can test when the mouse moves outside the toolbar window.  At that point call ReleaseCapTure()


Erick37, can you give me a simple overview of how to use an API?  I have never used one before.  Also any sample code would be helpful.

The following code demonstrates the use of the Get/Set/ReleaseCapture API calls. Note, the height of the menu bar is made negative because the Form coordinates are (0,0) one pixel below the bottom left corner of menu bar. Note also one problem with this method -- if the user moves *above* the form and re-enters, the form does not receive focus, so the status bar cannot be updated. The user must move onto the form and then over the menu bar.

A solution for this is to *not* call "ReleaseCapture" in the MouseMove event, however this has the unwanted side effect that it is necessary to click twice on the menu item (and then the problem described above comes into play again.)

Hope this helps,



Option Explicit

' API call to get various metrics (e.g. size of visible window, menu bar height etc.)
Private Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As Integer) As Integer

' API calls to control which window receives mouse movement
Private Declare Function ReleaseCapture Lib "user32" () As Long
Private Declare Function GetCapture Lib "user32" () As Long
Private Declare Function SetCapture Lib "user32" (ByVal hWnd As Long) As Long

' menu bar height constant
Private Const SM_CYMENUSIZE = 55

Private ml_MenuHeight As Long, ml_Width As Long, ml_Height As Long

Private Sub Form_Load()
    ' get the height of the menu bar in twips
    ml_MenuHeight = -ScaleY(GetSystemMetrics(SM_CYMENUSIZE), vbPixels, vbTwips)
    ' make sure we have width and height in Twips
    ml_Width = ScaleX(ScaleWidth, ScaleMode, vbTwips)
    ml_Height = ScaleY(ScaleHeight, ScaleMode, vbTwips)
End Sub

Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    ' if we don't have the mouse captured, capture it
    If GetCapture() <> hWnd Then
        SetCapture hWnd
    End If
    ' check if we're within the bounds of the form
    If X < 0 Or X > ml_Width Or Y < ml_MenuHeight Or Y > 0 Then
        ' outside the permitted bounds, release the capture
        ' clear the status bar here
        ' update the status bar here
    End If
End Sub


jjsc, You say "if the user moves *above* the form and re-enters, the form does not receive focus, so the status bar cannot be updated".  So if my form is always maximized I will not need to worry about this problem?
Top Expert 2005

John's code is essentially correct, however, I would put the code inside the ToolBar MouseMove event.
If you do not, then moving the mouse into the toolbar from the top, then moving it out again will not have the desired effect.
This one is on us!
(Get your first solution completely free - no credit card required)


Thanks everybody.  Sorry I can't accept more than one answer.  They should invent a way to divide up points.  Oh well, Erick37, I'll give you the points next time.  You are on my "people I have screwed over giving points to because I can only give points to one person" list; so I will be sure to keep that in mind if you answer any of my future questions.

Now I feel guilty :-) But in my (poor and limited) defense, when I originally read the question, Erick37 hadn't posted a comment, and I was already building a sample based on code I use...

Top Expert 2005

You can make it up by figuring out a way to press ToolBar buttons while the mouse is captured.

OK, after much thought and a little digging, I came up with the following solution (which incidentally has solved exactly the same problem I already had with GetCapture :-)

Drop the following code into a BAS module, e.g. MCapture.bas


Option Explicit

' functions to capture all output for a particular window
Public Declare Function GetCapture Lib "user32" () As Long
Public Declare Function SetCapture Lib "user32" (ByVal hWnd As Long) As Long
Public Declare Function ReleaseCapture Lib "user32" () As Long

' send events as if they came from the mouse
Public Declare Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long)

' get device information
Public Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long

' find the cursor
Public Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long

' for obtaining current screen dimensions
Public Const SM_CXSCREEN = 0
Public Const SM_CYSCREEN = 1

' constants for sending correct mouse event
Public Const MOUSEEVENTF_LEFTDOWN = &H2     '  left button down
Public Const MOUSEEVENTF_LEFTUP = &H4       '  left button up
Public Const MOUSEEVENTF_RIGHTDOWN = &H8    '  right button down
Public Const MOUSEEVENTF_RIGHTUP = &H10     '  right button up
Public Const MOUSEEVENTF_MIDDLEDOWN = &H20  '  middle button down
Public Const MOUSEEVENTF_MIDDLEUP = &H40    '  middle button up
Public Const MOUSEEVENTF_ABSOLUTE = &H8000  '  absolute move

Public Type POINTAPI
    X As Long
    Y As Long
End Type

Public Sub MouseClick(hWnd As Long, ByVal Button As MouseButtonConstants)
    ' store current coordinates
    Dim pt As POINTAPI
    ' dummy result, screen width and height
    Dim res As Long, scrX As Long, scrY As Long
    ' current mouse coordinates
    Dim curX As Long, curY As Long
    ' selected operation (left, middle, right button)
    Dim mouseDown As Long, mouseUp As Long
    ' get the dimensions of the current display
    scrX = GetSystemMetrics(SM_CXSCREEN)
    scrY = GetSystemMetrics(SM_CYSCREEN)
    ' get the current cursor position
    res = GetCursorPos(pt)
    ' convert to Mouse coordinates (0-65535, 0-65535)
    curX = pt.X * &HFFFF& / scrX
    curY = pt.Y * &HFFFF& / scrY
    ' select the event we want to send
    Select Case Button
        Case vbLeftButton
            mouseDown = MOUSEEVENTF_LEFTDOWN
            mouseUp = MOUSEEVENTF_LEFTUP
        Case vbMiddleButton
            mouseDown = MOUSEEVENTF_MIDDLEDOWN
            mouseUp = MOUSEEVENTF_MIDDLEUP
        Case vbRightButton
            mouseDown = MOUSEEVENTF_RIGHTDOWN
            mouseUp = MOUSEEVENTF_RIGHTUP
    End Select
    ' send it. Note, need to send mouseDown AND mouseUp
    mouse_event MOUSEEVENTF_ABSOLUTE Or mouseDown, curX, curY, 0, 0
    mouse_event MOUSEEVENTF_ABSOLUTE Or mouseUp, curX, curY, 0, 0
End Sub


Now, to test the code, drop a toolbar onto a new form, add a few buttons and add the following code:


Option Explicit

Private Sub Toolbar1_ButtonClick(ByVal Button As MSComctlLib.Button)
    Debug.Print "Clicked button " & Button.Index
End Sub

Private Sub Toolbar1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    ' if we don't have the mouse captured, capture it
    If GetCapture() <> Toolbar1.hWnd Then
        SetCapture Toolbar1.hWnd
    End If
    ' check if we're within the bounds of the form
    If X < 0 Or X > Toolbar1.Width Or Y < 0 Or Y > Toolbar1.Height Then
        ' no, release the capture
    End If
End Sub

Private Sub Toolbar1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
    ' click releases capture, so we only need to call the click function while capture is set.
    If GetCapture() = Toolbar1.hWnd Then
        MouseClick Toolbar1.hWnd, Button
    End If
End Sub


Notice that the MouseClick event should be in the MouseUp event of the toolbar (or whichever control has the focus captured) and you need to check if focus is still captured to prevent sending 2 events after the first click.

I hope that covers my penance :-)



Gain unlimited access to on-demand training courses with an Experts Exchange subscription.

Get Access
Why Experts Exchange?

Experts Exchange always has the answer, or at the least points me in the correct direction! It is like having another employee that is extremely experienced.

Jim Murphy
Programmer at Smart IT Solutions

When asked, what has been your best career decision?

Deciding to stick with EE.

Mohamed Asif
Technical Department Head

Being involved with EE helped me to grow personally and professionally.

Carl Webster
CTP, Sr Infrastructure Consultant
Empower Your Career
Did You Know?

We've partnered with two important charities to provide clean water and computer science education to those who need it most. READ MORE

Ask ANY Question

Connect with Certified Experts to gain insight and support on specific technology challenges including:

  • Troubleshooting
  • Research
  • Professional Opinions
Unlock the solution to this question.
Join our community and discover your potential

Experts Exchange is the only place where you can interact directly with leading experts in the technology field. Become a member today and access the collective knowledge of thousands of technology experts.

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.


Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.