
Introduction
This article illustrates how to implement a tray mouse hover/leave message.
The Problem
Some programs want to get a mouse hover/leave message from the system tray when they want to show a popup window that is not a tool tip. However, the Windows shell doesn't support it. We can only get mouse move, up, down, and double-click messages from the system tray.
It is very easy to implement a 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 the window of a 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 the tray icon. This class saves the mouse point whenever a WM_MOUSEMOVE message fires on the system tray, and then another thread compares it with the current mouse point. The thread fires a WM_MOUSELEAVE message when the two points are different.
The following code is the 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 that 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 and traypos.cpp file to your project.
- Declare a variable of this class like that.
Note that this class instance exists until the tray icon is deleted, so you must declare it a member variable or a global variable.
CMsgTrayPos traypos;
Add the following code after the register tray by calling Shell_NotifyIcon.
The three parameters—hwnd, uID, and uMsgID—are the same value as the member of NOTIFYICONDATA.
traypos.SetNotifyIconInfo(hwnd, uID, uMsgID);
Call CMsgTrayPos::OnMouseMove on your WM_MOUSEMOVE message handler from the system tray.
Now, you can add WM_MOUSEHOVER and WM_MOUSELEAVE messages to your tray message handler and write a code there.
CMsgTrayPos API
- VOID CMsgTrayPos::SetNotifyIconInfo(HWND hwnd, UINT uID, UINT uCallbackMsg);
This function provides tray icon inforamtion to the class. The three parameters—hwnd, uID, and uCallbackMsg—and members of NOTIFYICONDATA are the same.
VOID CMsgTrayPos::OnMouseMove()
This function is very important. You must call this function when you get a WM_MOUSEMOVE message from the system tray.
This function checks the mouse hover status and updates the mouse point internally.
- BOOL CMsgTrayPos::IsIconHover();
This function returns the mouse hover status. It returns TRUE if your mouse is on your tray icon.
History
- 22 Aug 2004—Initial upload.
Downloads