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;
The three parameters—hwnd, uID, and uMsgID—are the same value as the member of NOTIFYICONDATA.
traypos.SetNotifyIconInfo(hwnd, uID, uMsgID);
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()
- BOOL CMsgTrayPos::IsIconHover();
This function returns the mouse hover status. It returns TRUE if your mouse is on your tray icon.
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.
History
- 22 Aug 2004—Initial upload.