【WIN32之旅】给托盘图标加上MOUSE_ENTER、MOUSE_HOVER、MOUSE_LEAVE消息
来源:互联网 发布:新蛋现在怎么样 知乎 编辑:程序博客网 时间:2024/05/23 05:09
转载请说明原出处,谢谢~ http://blog.csdn.net/seven_1992/article/details/50848071
相信很多人在WIN32项目开发过程中涉及到托盘相关处理时都会碰到这样一个问题,无法获取托盘图标的鼠标移入(Mouse Enter)、移出(Mouse Leave)以及悬停(Mouse Hover)消息,因为WINDOWS只提供了一个WM_MOUSEMOVE消息给我们,想要实现更为复杂的界面逻辑,就比如自绘的ToolTip提示或者消息预览窗口那可怎么办呢?
说到这里,我想大伙们心底里一定都异口同声地表示揪心,不过没关系,我们这群爱捣鼓的也不吃吃素的人,让我们先来分析一下这几个消息的核心产生因素,我们知道时间是线性的,而程序的执行也是随时间呈线性的,所以我们不妨从时间上来分析我们需要的这几个消息与WM_MOUSEMOVE之间的关系:
PS. 首先我们要明白鼠标只要在托盘图标RECT区域中移动就会产生WM_MOUSEMOVE消息。
1.WM_MOUSE_ENTER(ENTER在时间上的表现为鼠标从LEAVE转变为ENTER,即第一次收到WM_MOUSEMOVE时)
2.WM_MOUSE_HOVER (HOVER在时间上的表现为间隔一定时长鼠标HOVER位置不变,即鼠标位置等于最后一次收到WM_MOUSEMOVE时的位置)
3.WM_MOUSE_LEAVE(LEAVE则正好与ENTER过程相反,即鼠标从ENTER转为了LEAVE状态)
从上面我们的分析我们可将在时间上呈线性的WM_MOUSEMOVE消息分解出我们所需要的WM_MOUSE_ENTER、WM_MOUSE_HOVER、WM_MOUSE_LEAVE消息,因此我们只需要利用上WIN32的定时器,无论托盘图标是在底部工具栏上还是托盘溢出区上,这都是一种比通过各种复杂方法获取托盘图标RECT区域,或者使用单独线程进行检测更为简便的方法。
下面就上关键代码吧:
/******************************************************************************* * @file TrayIconHandler.hpp 2016\3\10 17:47:38 $ * @author Jeffrey Tse <JeffreyTse.mail@gmail.com> * @brief Trayicon message handle program. ******************************************************************************/#define TRAYICON_HOVER_TIMER_ID 0x024#define TRAYICON_LEAVE_TIMER_ID 0x025class TrayIconHandler{public: enum _TrayIconMessage { WM_MOUSE_ENTER = 0x00F0, WM_MOUSE_HOVER, WM_MOUSE_LEAVE } TrayIconMessagepublic: TrayIconHandler(HWND hWnd, UINT uTrayIconMsg, UINT uHoverElapse = 300U) : m_hWnd(hWnd), m_uTrayIconMsg(uTrayIconMsg), m_uHoverElapse(uHoverElapse), m_bMouseEnter(FALSE){}; ~TrayIconHandler() { // 清除检测定时器 KillTimer(m_hMainHwnd, TRAYICON_HOVER_TIMER_ID); KillTimer(m_hMainHwnd, TRAYICON_LEAVE_TIMER_ID); }; LRESULT MessageNotify(TrayIconMessage uMsg) { // Do something ... } LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { HRESULT lRes = S_OK; switch (uMsg) { case m_uTrayIconMsg: lRes = OnTrayIconMessage(uMsg, wParam, lParam); break; case WM_TIMER: lRes = OnTimer(uMsg, wParam, lParam); break; default: break; } return lRes; } LRESULT OnTrayIconMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(lParam) { case WM_RBUTTONDOWN: { } break; case WM_LBUTTONDBLCLK: { } break; ... case WM_MOUSEMOVE: { if(!m_bMouseEnter) { m_bMouseEnter = TRUE; // DEBUG_STRING(_T("################# TRAYICON_ENTER #################\r\n")) // Do something ... MessageNotify(TrayIconMessage::WM_MOUSE_ENTER); } POINT pt; if(GetCursorPos(&pt)) // 获取当前鼠标位置 { if(pt.x != m_ptMouseHover.x || pt.y != m_ptMouseHover.y) { // 重置检测定时器 KillTimer(m_hMainHwnd, TRAYICON_HOVER_TIMER_ID); KillTimer(m_hMainHwnd, TRAYICON_LEAVE_TIMER_ID); SetTimer(m_hMainHwnd, TRAYICON_HOVER_TIMER_ID, m_uHoverElapse, NULL); SetTimer(m_hMainHwnd, TRAYICON_LEAVE_TIMER_ID, 200U, NULL); // 记录鼠标位置 m_ptMouseHover = pt; } } } break; return S_OK; } LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam) { if(wParam == TRAYICON_HOVER_TIMER_ID) { KillTimer(m_hMainHwnd, TRAYICON_HOVER_TIMER_ID); POINT pt; if(GetCursorPos(&pt)) { if(pt.x == m_ptMouseHover.x && pt.y == m_ptMouseHover.y) { // DEBUG_STRING(_T("################# TRAYICON_HOVER #################\r\n")) // Do something ... MessageNotify(TrayIconMessage::WM_MOUSE_HOVER); } } } else if(wParam == TRAYICON_LEAVE_TIMER_ID) { POINT pt; if(GetCursorPos(&pt)) { if(pt.x != m_ptMouseHover.x || pt.y != m_ptMouseHover.y) { m_bMouseEnter = FALSE; KillTimer(m_hMainHwnd, TRAYICON_HOVER_TIMER_ID); KillTimer(m_hMainHwnd, TRAYICON_LEAVE_TIMER_ID); // DEBUG_STRING(_T("################# TRAYICON_LEAVE #################\r\n")) // Do something ... MessageNotify(TrayIconMessage::WM_MOUSE_LEAVE); } } } return S_OK; }private: HWND m_hMainHwnd; // 主消息窗口 UINT m_uTrayIconMsg; // 注册的托盘通知消息 UINT m_uHoverElapse; // 停留时长 BOOL m_bMouseEnter; // 鼠标是否进入 POINT m_ptMouseHover; // 鼠标停留位置}
#include <windows.h>...TrayIconHandler handler(g_hWnd, WM_TRAYICON_NOTIFY);...// 窗口过程函数LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ){ switch (uMsg) { case WM_DESTROY: // 窗口销毁消息 PostQuitMessage( 0 ); // 发送退出消息 return 0; } // 调用处理windows消息 handler.HandleMessage(uMsg, wParam, lParam); return DefWindowProc( hwnd, uMsg, wParam, lParam );}
总而言之,虽然微软没有给我们所需要的检测鼠标进入、移出以及悬停托盘的消息,但只要我们静下心来认真思考仔细分析,我想我们总会会心一笑入浴春风,相信以上的内容能够帮助到正需要帮助的人。
1 0
- 【WIN32之旅】给托盘图标加上MOUSE_ENTER、MOUSE_HOVER、MOUSE_LEAVE消息
- 给ThemeButton加上图标
- 给我的程序加上托盘
- Qt学习之旅----给生成的.exe文件加上图标
- 给自定义控件加上图标
- VB:给菜单加上图标
- 给网站加上小图标
- 自学QT之托盘图标
- 托盘图标不响应消息 已解决
- 托盘图标的添加和消息响应
- 给托盘图标增加气球提示
- 给Windows mobile应用添加托盘图标
- 给Windows mobile应用添加托盘图标
- 也说给博客加上邮件图标
- 怎么给自己的程序加上图标
- 给网页加上个性小图标
- 如何给终端程序加上图标
- 如何给QT应用程序加上图标
- 自定义ViewGroup获取子View参数
- git学习笔记
- UBUNTU虚拟机器上配置Hadoop时遇到的问题以及经验
- Linux网络编程 IO多路复用
- 模拟器运行不了地图,真机可以
- 【WIN32之旅】给托盘图标加上MOUSE_ENTER、MOUSE_HOVER、MOUSE_LEAVE消息
- ArcGIS教程:地理处理服务示例(裁剪与发送)(一)
- poj1011-Sticks dfs各种剪枝
- 如何安装 CocoaPods
- hive的安装(元数据库: MySQL)
- 16进制编辑器
- oracle数据类型和对应的java类型
- 判断安卓应用处于前台或者后台
- QOS配置参数对HFSC算法的影响