Solved

Mouse move out of image/label

Posted on 2000-05-05
26
335 Views
Last Modified: 2008-02-26
How can I know when my mouse moved out of an image/label?
Using the old dragdrop method is nice, but there is a problem with the mouse pointer image (I want it to stay the same as the original!)
Using mousemove on the form is not good, because if I move quickly out of the form, I will not receive a mousemove event!
0
Comment
Question by:ViniT
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 10
  • 8
  • 4
  • +2
26 Comments
 
LVL 28

Expert Comment

by:AzraSound
ID: 2781777
you can subclass and track the mouses movement that way...here's an example you can download.

http://www.vb-helper.com/Howto/trackms2.zip
0
 
LVL 32

Expert Comment

by:Erick37
ID: 2781799
This works only on controls with a hwnd porperty (not labels).

Option Explicit

Private Declare Function SetCapture Lib "user32" _
    (ByVal hwnd As Long) As Long
Private Declare Function ReleaseCapture Lib "user32" () As Long

Private bCaptured As Boolean

Private Sub Picture1_Click()
    'Recapture mouse on click
    If bCaptured Then
        Call SetCapture(Picture1.hwnd)
    End If
End Sub

Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If Not bCaptured Then
        'Mouse has entered, set mouse capture
        bCaptured = True
        Call SetCapture(Picture1.hwnd)
        Debug.Print "Mouse In"
    'Check to see if mouse leaves boundaries
    ElseIf (X < 0) Or (Y < 0) Or _
            (X > Picture1.ScaleWidth) Or (Y > Picture1.ScaleHeight) Then
        Call ReleaseCapture
        bCaptured = False
        Debug.Print "Mouse Out"
    End If
End Sub
0
 

Author Comment

by:ViniT
ID: 2781862
Adjusted points from 100 to 150
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:ViniT
ID: 2781863
AzraSound, this example tracks the x and y of the mouse every milisecond of the timer. This is something I don't want to do in the application. Moveover, I need to save the X and Y coordinates of each control on the form relative to the current resolution and screen to know when I moved out!
I have many controls on the form, each time the user will move the form, I will need to save all the new points, this is nuts, too much work, and is too slow also.

Erick37, thanks for this example, but I need it for labels and images unfortunately... :-(
0
 

Author Comment

by:ViniT
ID: 2781892
AzraSound, by the way, the example doesn't subclass in order to find the mouse coordinates, but to track the movement on the systray icon.
0
 
LVL 28

Expert Comment

by:AzraSound
ID: 2781905
i assumed thats what it did.  upon downloading the sample myself i see that that is not the case.
0
 
LVL 28

Expert Comment

by:AzraSound
ID: 2781919
i apologize for being so abrupt and unreliable in my first post.  there are two demos here that prove to be more appropriate.  towards the bottom of the page under the label of Mouse:

http://www.mvps.org/vbvision/grouped_demos.htm
0
 

Author Comment

by:ViniT
ID: 2782982
Adjusted points from 150 to 200
0
 

Author Comment

by:ViniT
ID: 2782983
AzraSound, the two examples in this link do exactly what Erick37 showed - they work wonderful on PictureBox, but not on windowless objects...
0
 
LVL 3

Expert Comment

by:MTroutwine
ID: 2782992
Here is a not so elegant way to do this.  It doesn't require you to have an API call rather it uses five global variables to track the control size and to set if an event should be fired off.  You can try this by pasting in a new VB project adding a label control and an image control:

Option Explicit

Dim sngWidth As Single
Dim sngHeight As Single
Dim sngTop    As Single
Dim sngLeft   As Single
Dim blnMouseExit As Boolean


Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
   
    If blnMouseExit = True Then
        If X > sngWidth Or Y > sngHeight Or X < sngLeft Or Y < sngTop Then
            MsgBox "Mouse is out of the control!"
        End If
    End If
   
    blnMouseExit = False
End Sub


Private Sub Image1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    sngWidth = Image1.Width
    sngHeight = Image1.Height
    sngTop = Image1.Top
    sngLeft = Image1.Left
    blnMouseExit = True
End Sub

Private Sub Label1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
       
    sngWidth = Label1.Width
    sngHeight = Label1.Height
    sngTop = Label1.Top
    sngLeft = Label1.Left
    blnMouseExit = True
   
End Sub
0
 

Author Comment

by:ViniT
ID: 2783019
Thanks MTroutwine, but if you read my question, I said I don't want to use the form_mousemove because it doesn't track fast movement.
0
 
LVL 3

Expert Comment

by:MTroutwine
ID: 2783021
Copy that...
0
 

Author Comment

by:ViniT
ID: 2783034
I did.
Put Label1 or Image1 very close to the border of your form.
Stand on the label/image and move very quickly out of the form.

see my point?
0
 
LVL 3

Expert Comment

by:MTroutwine
ID: 2783051
Copy that...
0
 
LVL 3

Expert Comment

by:MTroutwine
ID: 2783053
Sorry about that I meant I understood, I must have refreshed the same old message.  Sorry again!

:>)
0
 
LVL 15

Expert Comment

by:ameba
ID: 2783086
What is the purpose of catching this 'un-hover' event?

If you are Highlighting controls, or you are showing custom ToolTips, you can use *timer* for this:

>I need to save the X and Y coordinates of each control on the form relative to the current resolution and screen to know when I moved out!
No, you only save rectangle of the currenly highlighted control and check if mouse coords are inside this rectangle.
0
 
LVL 28

Expert Comment

by:AzraSound
ID: 2783123
for the label you can substitute a picturebox, give it no border and draw text to it so it appears as a label, then you can use the methods mentioned above.  any chances of substituting it for the imagebox as well?
0
 
LVL 28

Expert Comment

by:AzraSound
ID: 2783128
actually what am i thinking, substitute a textbox for the label
0
 

Author Comment

by:ViniT
ID: 2783147
AzraSound - problem is I want to show the background of the form.
And unfortunately, PictureBoxes/Frames/TextBoxes can't be transparent!

Ameba - im checking out your comment in my project, if it works fine, I'll grant you the points :-)
0
 
LVL 28

Expert Comment

by:AzraSound
ID: 2783158
what color is your form?  you can change the backcolor
0
 

Author Comment

by:ViniT
ID: 2783202
There is a picture back there :-)
0
 
LVL 28

Expert Comment

by:AzraSound
ID: 2783205
is this program for personal use or are you going to be redistributing it?  if its only for personal use, use the textbox and imagebox provided in the Forms 2.0 library..they both support transparency
0
 
LVL 15

Accepted Solution

by:
ameba earned 200 total points
ID: 2783262
ViniT, for highlighting, here is the sample:

' Form, add Checkbox, Timer, Image (index=0) and one Label control (index=0)
Option Explicit

Private Sub Form_Load()
    Timer1.Interval = 200
    Check1.Caption = "Bold"
   
    Check1.Move 900, 90, 900, 255
    Image1(0).Picture = Me.Icon
    Image1(0).Move 0, 0
    Image1(0).Appearance = 0
    Label1(0).AutoSize = True
    Label1(0).Move 0, 690
    ' add some controls
    Dim x As Frame, i As Integer
    Set x = Controls.Add("vb.frame", "Frame1")
    x.Move 0, ScaleHeight / 2, ScaleWidth / 3, ScaleHeight / 2
    x.Visible = True
    For i = 1 To 6
        Load Image1(i)
        Image1(i).Move (i - 1) * 990 + 120, (i - 1) * 600 + 180
        Image1(i).Visible = True
        If i < 3 Then Set Image1(i).Container = Me.Controls("Frame1")
        Load Label1(i)
        Label1(i).Move (i - 1) * 990 + 120, i * 600 + 180
        Label1(i).Visible = True
        If i < 3 Then Set Label1(i).Container = Me.Controls("Frame1")
    Next
End Sub

Private Sub Timer1_Timer()
    tmrHiLiteProc
End Sub

Private Sub Check1_Click()
    UseBold = CBool(Check1.Value)
End Sub

Private Sub Check1_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
    Hilite Check1
End Sub
Private Sub Image1_MouseMove(Index As Integer, Button As Integer, Shift As Integer, x As Single, y As Single)
    Hilite Image1(Index)
End Sub
Private Sub Label1_MouseMove(Index As Integer, Button As Integer, Shift As Integer, x As Single, y As Single)
    Hilite Label1(Index)
End Sub


'------------------------------------------------------------------------------
' modHilite.bas module, created by Bruno Paris
Option Explicit
Private curCtl As Control
Public UseBold As Boolean
' APIs
Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type
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 ClientToScreen Lib "user32" _
    (ByVal hWnd As Long, lpPoint As POINTAPI) As Long
Private Declare Function PtInRect Lib "user32" (lpRect As RECT, _
    ByVal ptx As Long, ByVal pty As Long) As Long

Public Sub Hilite(pCtl As Control)
    Dim i As Integer
    On Error Resume Next
    If curCtl Is pCtl Then Exit Sub ' do not repeat
    ' restore previous control state
    If TypeOf curCtl Is Label _
        Or TypeOf curCtl Is OptionButton _
        Or TypeOf curCtl Is CheckBox _
        Then
        curCtl.ForeColor = vbButtonText ' button text color
        curCtl.FontBold = False
    ElseIf TypeOf curCtl Is Image Then
        curCtl.BorderStyle = 0
    End If
    ' HiLite new control
    Set curCtl = pCtl
    If TypeOf curCtl Is Label _
        Or TypeOf curCtl Is OptionButton _
        Or TypeOf curCtl Is CheckBox _
        Then
        curCtl.ForeColor = vbHighlight  ' HiLite system color
        If UseBold Then curCtl.FontBold = True
    ElseIf TypeOf curCtl Is Image Then
        curCtl.BorderStyle = 1
    End If
End Sub

Public Sub unHiLite()
    On Error Resume Next
    If TypeOf curCtl Is Label _
        Or TypeOf curCtl Is OptionButton _
        Or TypeOf curCtl Is CheckBox _
        Then
        curCtl.ForeColor = vbButtonText ' button text color
        curCtl.FontBold = False
    ElseIf TypeOf curCtl Is Image Then
        curCtl.BorderStyle = 0
    End If
    Set curCtl = Nothing
End Sub

Public Sub tmrHiLiteProc()
    If MouseIsOver(curCtl) = False Then unHiLite
End Sub

Private Function MouseIsOver(ctl As Control) As Boolean
    Dim pt As POINTAPI, rc As RECT
   
    GetCursorPos pt         ' get cursor position
    rc = GetRect(ctl)    ' control rectangle
    MouseIsOver = PtInRect(rc, pt.x, pt.y)
End Function

Private Function GetRect(ctl As Control) As RECT
' we cannot use API GetWindowRect directly, light controls don't have hwnd
' this works also for non-lite controls
' ScaleMode must be vbTwips!
    Dim px As Integer, py As Integer
    Dim ret As Long, pt As POINTAPI
    Dim objParent As Object ' form or control
    On Error Resume Next
   
    px = Screen.TwipsPerPixelX
    py = Screen.TwipsPerPixelY
    Set objParent = ctl.Container ' form or container control
    ' convert point (0,0) to screen coordinate
    ret = ClientToScreen(objParent.hWnd, pt)
    ' pt contains screen coordinates of client point 0,0
    ' to get rectangle, use Ctl.left, .top, .width and .height properties
    GetRect.Left = pt.x + ctl.Left / px
    GetRect.Right = GetRect.Left + ctl.Width / px
    GetRect.Top = pt.y + ctl.Top / py
    GetRect.Bottom = GetRect.Top + ctl.Height / py
End Function
0
 
LVL 28

Expert Comment

by:AzraSound
ID: 2783420
one more suggestion...possibly consider using api functions.  use bitblt to paint the picture to the form directly and use drawtext as a label.  no controls needed this way and now tracking the mouses position will work.
0
 

Author Comment

by:ViniT
ID: 2783497
Thanks!
0
 
LVL 15

Expert Comment

by:ameba
ID: 2783612
Thanks for the points!
0

Featured Post

SharePoint Admin?

Enable Your Employees To Focus On The Core With Intuitive Onscreen Guidance That is With You At The Moment of Need.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…

719 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question