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






3.36/5 (9 votes)
Aug 24, 2004
2 min read

87397

1607
Ever wanted to get mouse hover/leave message from system tray? Windows shell doesn't support that. This class is a solution that works.
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 ofNOTIFYICONDATA
.traypos.SetNotifyIconInfo(hwnd, uID, uMsgID);
- Call
CMsgTrayPos::OnMouseMove
on yourWM_MOUSEMOVE
message handler from system tray. - Now you can add
WM_MOUSEHOVER
andWM_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 ofNOTIFYICONDATA
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.