Click here to Skip to main content
Click here to Skip to main content

How to implement mouse hover/leave message on system tray.

By , 23 Aug 2004
 

Introduction

This article illustrates how to implement tray mouse hover/leave message.

The problem

Some programs want to get mouse hover/leave message from system tray when they want to show popup window which is not tool tip. However, Windows shell doesn't support it. We can only get mouse move, up, down, and double click message from system tray.

It is very easy to implement WM_MOUSEHOVER message because the first WM_MOUSEMOVE is that. But WM_MOUSELEAVE is hard to implement, so I decided to write a compact class to notify a window of mouse hover/leave message.

The idea

The basic idea is very simple. It is that no WM_MOUSEMOVE message fires when the mouse is out of tray icon. This class saves mouse point whenever WM_MOUSEMOVE message fires on system tray, and then, another thread compares it with the current mouse point. The thread fires WM_MOUSELEAVE message when the two points are different.

The following code is WM_MOUSEMOVE handler:

VOID CTrayPos::OnMouseMove()
{
    EnterCriticalSection(&m_cs);

    GetCursorPos(&m_ptMouse);
    if(m_bTrackMouse == FALSE)
    {
        OnMouseHover();
        m_bTrackMouse = TRUE;
    }

    LeaveCriticalSection(&m_cs);
}

This is a thread function which checks the mouse point.

UINT CALLBACK CTrayPos::TrackMousePt(PVOID pvClass)
{
    POINT       ptMouse;
    CTrayPos    *pTrayPos = (CTrayPos *) pvClass;

    while(WaitForSingleObject(pTrayPos->m_hExitEvent, 2000) == WAIT_TIMEOUT)
    {

        if(pTrayPos->m_bTrackMouse == TRUE)
        {
            GetCursorPos(&ptMouse);
            
            if(ptMouse.x != pTrayPos->m_ptMouse.x || 
                      ptMouse.y != pTrayPos->m_ptMouse.y)
            {
                pTrayPos->m_bTrackMouse = FALSE;
                pTrayPos->OnMouseLeave();
            }
        }
    }

    return 0;
}

Using the code

If you want to use this class in your project - just follow these simple steps.

  • Add traypos.h, traypos.cpp files to your project.
  • Declare a variable of this class like that:
    CMsgTrayPos traypos; 

    Note that this class instance exists until the tray icon is deleted, so you must declare it as a member variable or a global variable.

  • Add the following code after registering tray by calling Shell_NotifyIcon.

    The three parameters -- hwnd, uID, uMsgID -- are the same value which is the member of NOTIFYICONDATA.

    traypos.SetNotifyIconInfo(hwnd, uID, uMsgID);
  • Call CMsgTrayPos::OnMouseMove on your WM_MOUSEMOVE message handler from system tray.
  • Now you can add WM_MOUSEHOVER and WM_MOUSELEAVE messages to your tray message handler and write code there.

CMsgTrayPos API

  • VOID CMsgTrayPos::SetNotifyIconInfo(HWND hwnd, UINT uID, UINT uCallbackMsg);

    This function provides tray icon information to the class. The three parameters -- hwnd, uID, uCallbackMsg -- and members of NOTIFYICONDATA are the same.

  • VOID CMsgTrayPos::OnMouseMove()

    This function is very important. You must call this function when you get WM_MOUSEMOVE message from system tray. This function checks mouse hover status and updates mouse point internally.

  • BOOL CMsgTrayPos::IsIconHover();

    This function returns mouse hover status. It returns TRUE if your mouse is on your tray icon.

History

  • 22 Aug 2004 - Initial upload.

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

YoungJin Shin
Korea (Republic Of) Korea (Republic Of)
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberhacysean29 May '11 - 21:43 
good..
GeneralcoolmemberLehi6 Jan '05 - 12:13 
Smile | :)
GeneralAlternate way to get mouse enter/leavememberJim Crafton24 Aug '04 - 6:04 
what if you tried this? This means you don't have to have another thread and worry about multi-threading issues.
 

case WM_MOUSEMOVE: {
  if ( !mouseEnteredControl_ ) {
    TRACKMOUSEEVENT trackmouseEvent = {0,0,0,0};
    trackmouseEvent.cbSize = sizeof(trackmouseEvent);
    trackmouseEvent.dwFlags = TME_LEAVE;
    trackmouseEvent.hwndTrack = hwnd_;
    trackmouseEvent.dwHoverTime = HOVER_DEFAULT;
    if ( _TrackMouseEvent( &trackmouseEvent ) ) {
      //mouse entered code here
    }
  }
  mouseEnteredControl_ = true;
}
break;
 
 

MSDN Info on _TrackMouseEvent[^]
 
This should then push WM_MOUSELEAVE and WM_MOUSEENTER message back to you.
 

 
¡El diablo está en mis pantalones! ¡Mire, mire!
 
Real Mentats use only 100% pure, unfooled around with Sapho Juice(tm)!
 
SELECT * FROM User WHERE Clue > 0
0 rows returned

GeneralRe: Alternate way to get mouse enter/leavememberShin, YoungJin24 Aug '04 - 8:16 
_TrackMouseEvent, TrackMouseEvent work with hwnd region.
It doesn't work with tray. I tested it.
Is this wrong?
GeneralRe: Alternate way to get mouse enter/leavememberJim Crafton24 Aug '04 - 10:41 
Nothing neccessarily wrong with your approach other than having to be real careful about getting the thread implementation correct and not accidentally calling non thread safe functions.
 
¡El diablo está en mis pantalones! ¡Mire, mire!
 
Real Mentats use only 100% pure, unfooled around with Sapho Juice(tm)!
 
SELECT * FROM User WHERE Clue > 0
0 rows returned

GeneralSweet!memberJim Crafton24 Aug '04 - 5:46 
Schwing!
Hell I gave you 5 just for the great screenshot! Smile | :)
Made my day Smile | :)

 
¡El diablo está en mis pantalones! ¡Mire, mire!
 
Real Mentats use only 100% pure, unfooled around with Sapho Juice(tm)!
 
SELECT * FROM User WHERE Clue > 0
0 rows returned

GeneralRe: Sweet!memberShin, YoungJin24 Aug '04 - 8:17 
thanks ^^

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 24 Aug 2004
Article Copyright 2004 by YoungJin Shin
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid