5,693,062 members and growing! (14,532 online)
Email Password   helpLost your password?
Languages » VBScript » General     Advanced

Adding MouseLeave, MouseHover events to VB6 Controls

By hspc

This article is about creating ActiveX controls in Visual Basic 6 that has two extra mouse Events : MouseLeave ,MouseHover.
VBScript, VB 6, VBWindows, Win2K, WinXP, Win2003Visual Studio, Dev

Posted: 24 Apr 2004
Updated: 24 Apr 2004
Views: 47,083
Bookmarked: 6 times
Announcements
Loading...



Search    
Advanced Search
Sitemap
9 votes for this Article.
Popularity: 3.82 Rating: 4.00 out of 5
0 votes, 0.0%
1
1 vote, 11.1%
2
1 vote, 11.1%
3
4 votes, 44.4%
4
3 votes, 33.3%
5
Note: This is an unedited contribution. If this article is inappropriate, needs attention or copies someone else's work without reference then please Report This Article

Sample Image - Link_Label_Sample.jpg

Introduction

This article is about creating ActiveX controls in Visual Basic 6 that has two extra mouse Events:

  1. MouseLeave : raised when the cursor get out of the control.
  2. MouseHover : Raised when the user pouses the cursor over the control for a defined time (default is 400 Milliseconds).

A famous approach to achieve this is to use a Timer control with a small interval. And in the timer event the programmer checks the cursor location. (I do hate this.It's Painful and needs a lot of work and overhead to track the cursor).
Another way is to start using VB.NET which has these events built-in..(But you should have stronger reasons to switch to .NET !!).
The alternative way used in this article is to let windows send you a MouseLeave,MouseHover Messages (Events).

How to do this ?

We need 3 things to achieve this :

  1. To tell windows that you want it to send you the required events.
    this is achived by calling TrackMouseEvent API function specifying Events you need and the hover time you want.This is done in the main module (mdlProc.bas) in the RequestTracking Function.
    Dim trk As tagTRACKMOUSEEVENT
    trk.cbSize = 16
    trk.dwFlags = TME_LEAVE Or TME_HOVER
    trk.dwHoverTime = trak.HoverTime
    trk.hwndTrack = trak.hwnd
    
    TrackMouseEvent trk
        
  2. To receive the message when windows sends it.
    Visual Basic does not have a built-in mechanism to receive custom messages. You can only choose from a list of events in the form or control code window.
    So we need to Subclass the control's window to intercept all messages sent to the window.Then we can handle the messages we need and forward the rest to the original window procedure. this is done by calling SetWindowLong API to set the new window procdure :
    SetWindowLong(ctl.hwnd, GWL_WNDPROC, AddressOf WindowProc)

    the WindowProc Function is defined in mdlProc.bas like this :
    Private Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

    We need to handle 3 specific messages : WM_MOUSELEAVE,WM_MOUSEHOVER,WM_MOUSEMOVE and forward other messages (as well as the WM_MOUSEMOVE message) directly to the original window procedure :

    WindowProc = CallWindowProc(trak.PrevProc, hwnd, uMsg, wParam, lParam)
  3. We need to dispatch the meassge to the window :
    Note that all messages are sent to the WindowProc Function.But we may have multiple controls on the form. so we want to know which control was this message originally sent to.
    To make this, we use a collection trackCol to hold references to clsTrackInfo objects. And the keys of the collection are the window handles (hwnd). I use window handles as keys because WindowProc Function receives the window handle as a parameter.So we can use it to lookup the clsTrackInfo object in the collection.

    to add the control to the collection :
    trackCol.Add trak, CStr(trak.hwnd)
    To search for the requires control :
    Set trak = trackCol.Item(CStr(hwnd))
    then we use this code to check the value of the message and take the required action.
    If uMsg = WM_MOUSELEAVE Then
        trak.RaiseMouseLeave
    ElseIf uMsg = WM_MOUSEHOVER Then
        trak.RaiseMouseHover
    ElseIf uMsg = WM_MOUSEMOVE Then
        RequestTracking trak
        WindowProc = CallWindowProc(trak.prevProc, hwnd, uMsg, wParam, lParam)
    Else
        WindowProc = CallWindowProc(trak.prevProc, hwnd, uMsg, wParam, lParam)
        'Debug.Print uMsg
    
    End If
    

Sceleton of the control :

In the mdlProc.bas I use the clsTrackInfo to be stored in the trackCol collection. these objects in the collection are used to connect the module code to the UserControl.
It makes more sense to store references to the UserControl directly..But this causes the Terminate event not to be raised in some cases due to cerculer references.
(More about this in :Knowledge base)

Control's sceleton code:

note that I declared MyTrak with events :

Dim WithEvents MyTrak As clsTrackInfo
Code:
Option Explicit

Public Event MouseLeave()
Public Event MouseHover()

Dim WithEvents MyTrak As clsTrackInfo

Private Sub MyTrak_MouseHover()
RaiseEvent MouseHover
End Sub

Private Sub MyTrak_MouseLeave()
RaiseEvent MouseLeave
End Sub

Public Property Get HoverTime() As Long
HoverTime = MyTrak.HoverTime
End Property

Public Property Let HoverTime(newHoverTime As Long)
MyTrak.HoverTime = newHoverTime
PropertyChanged "HoverTime"
End Property

Private Sub UserControl_InitProperties()
Set MyTrak = New clsTrackInfo
End Sub

Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
Set MyTrak = New clsTrackInfo
MyTrak.hwnd = UserControl.hwnd

MyTrak.HoverTime = PropBag.ReadProperty("HoverTime", 400)

If Ambient.UserMode Then
StartTrack MyTrak
End If
End Sub

Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
PropBag.WriteProperty "HoverTime", MyTrak.HoverTime, 400
End Sub

Private Sub UserControl_Terminate()
EndTrack MyTrak
Set MyTrak = Nothing
End Sub

I handle MyTrak_MouseHover and MyTrak_MouseLeave events of MyTrak object to raise the required events.

Notes:

  1. StartTrack is called in the UserControl_ReadProperties to start tracking the events and add the control to the trackCol Collection. and EndTrack is called in the UserControl_Terminate event to end tracking and remove the control from the trackCol Collection.
    I used UserControl_ReadProperties not UserControl_Initialize to be able to check the Ambient.UserMode property which is not available in the UserControl_Initialize event.
  2. WM_MOUSEHOVER is sent when the user pauses the mouse over the control for a specific time. the default hover time is 400 millisconds (the same as windows default) but you can change it.
  3. After the first time windows send the WM_MOUSEHOVER or WM_MOUSELEAVE events it does not resend them till you re-request this. so I call RequestTracking when WM_MOUSEMOVE message is sent.
  4. Set the Instancing property of clsTrackInfo to private.
  5. Take care when changing this article's code or generaly when using window subclassing in Visual Basic. My IDE crashed many times before I could make it work fine !!.
  6. Handle all errors in MouseLeave ,MouseHover and MouseMove Event handlers. Any un handled errors can make the IDE or the application to crash or give more errors. So using On Error ... goto.. or On Error Resume Next is advisable.
    Also in the error trapping (Tools->Options->General tab) select break on unhandled errors or break in class module not break on all errors.
  7. It's always better not to end your application using End or by clicking End in the IDE..This causes Terminate Events not to be called.

If you don't understand all the above :

You still can use the code.

  1. Create a new ActiveX Control project.
  2. Add the mdlProc.bas , clsTrackInfo.cls to the project.
  3. Copy and paste the sceleton code above to your control.

Please feel free to contact the author for any questions or comments using this forum.

 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

hspc


I started programming with GWBasic as a hobby during high school and then with VB6 throughout college, where I majored in Structural Engineering. In my final year of college, I decided to change over to programming. Currently, I work as a Lead Software Engineer building educational portals. My programming skills include C++, C#.NET, VB .NET, PHP, MS SQL Server, and MySQL. I also started post graduate studies in computer science.
Occupation: Team Leader
Location: Egypt Egypt

Other popular VBScript articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 7 of 7 (Total in Forum: 7) (Refresh)FirstPrevNext
GeneralMouseHover - MouseLeavememberDon Putch13:44 18 Feb '07  
GeneralRe: MouseHover - MouseLeavememberhspc3:02 23 Feb '07  
GeneralRe: MouseHover - MouseLeavememberDon Putch8:13 23 Feb '07  
GeneralMSHFlexGrid Problemmembersabankocal0:05 29 Jul '05  
GeneralDoesn't always work!!!sussAnonymous15:00 17 Oct '04  
GeneralRe: Doesn't always work!!!memberhspc0:13 23 Oct '04  
GeneralMessage From AvinashmemberAvinash_Sonu18:42 7 Sep '04  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 24 Apr 2004
Editor:
Copyright 2004 by hspc
Everything else Copyright © CodeProject, 1999-2008
Web19 | Advertise on the Code Project