转载请说明原出处,谢谢~ 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_ENTERWM_MOUSE_HOVERWM_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 );
}

总而言之,虽然微软没有给我们所需要的检测鼠标进入、移出以及悬停托盘的消息,但只要我们静下心来认真思考仔细分析,我想我们总会会心一笑入浴春风,相信以上的内容能够帮助到正需要帮助的人。

【WIN32之旅】给托盘图标加上MOUSE_ENTER、MOUSE_HOVER、MOUSE_LEAVE消息相关推荐

  1. 【WIN32之旅】WINDOWS错误处理与参考(四)

    转载请说明原出处,谢谢~ http://blog.csdn.net/seven_1992/article/details/44497435 上一篇,我们说到了GetLastError()函数,可是它返 ...

  2. WIN32下实现输入法所需要的一些必要消息、函数和说明

    IME消息 以下列出IME中用到的消息. WM_IME_CHAR(IME得到了转换结果中的一个字符) WM_IME_COMPOSITION(IME根据用户击键的情况更改了按键组合状态) WM_IME_ ...

  3. Python发送微信消息(文字、图片、文件)给指定好友和微信群(调用Win32 API模拟人的手动操作来发送消息)

    本示例是调用Windows API模拟发送,用Python调用win32api这个库来调用Windows API模拟人的手动操作来发送消息. 在使用前,请将你微信的窗口设置为在最前面,这样就便于程序找 ...

  4. 《C++字符串完全指南——第一部分:win32 字符编码》

    <C++字符串完全指南--第一部分:win32 字符编码>     原作者:Michael Dun 译    者:Dingqiao Wang 引言 毫无疑问,你肯定见过像TCHAR, st ...

  5. 【win32汇编】0x04 第一个窗口程序

    第一个win32汇编窗口程序,主要来自 win32汇编语言程序设计,然后加上了自己查阅msdn文档的一些理解,基本过程: start入口地址 --> _WinMain主函数 --> 定义一 ...

  6. 利用Python和win32编程范例——按需定制一个按键精灵

    转自:作者 橘子一方 http://www.orangecube.net/articles/python-win32-example.html 利用Python和win32编程范例--按需定制一个按键 ...

  7. win32汇编使用win32 api实现字符串拷贝

    字符串拷贝,调用win32的lstrcpy函数:拷贝了以后用消息框显示一下: .386 .model flat, stdcall option casemap :noneinclude S:\masm ...

  8. 图解Dev C++ 创建Win32 项目模板

    打开Dev C++,新建一个项目: 在Windows程序设计第五版源码中,找到第10章,PoePoem例子:把PoePoem.c代码拷贝到main.cpp中: 用它来作为一个模板:PoePoem.c比 ...

  9. win32开发(简单绘图)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 在win32上面,所有的操作都是通过消息来完成的.正如前面一节说的那样,WM_CREATE.WM ...

最新文章

  1. mysql执行事务的语句_详解MySQL执行事务的语法和流程
  2. java架构师,必须掌握的几点技术?
  3. linux上通过lighttpd上跑一个C语言的CGI小页面以及所遇到的坑
  4. Cordova 本地项目创建方法
  5. JSON.stringify()中文乱码
  6. 程序员的数学笔记3--迭代法
  7. linux 命令行 播放器,Linux下基于命令行的音乐播放器
  8. Django Celerybeat日志报错处理('NoneType' object has no attribute 'is_due')
  9. 使用qBittorrent下载bt种子文件
  10. Openstack 虚拟机通讯
  11. kvaser canking 的使用
  12. 线程安全的随机数生成
  13. matlab如何表示冲激信号,matlab里如何表示冲激信号
  14. openfire主要插件介绍
  15. linux系统下的程序开发报告册,linux系统及其应用(应用开发)实验报告册.doc
  16. 说一说递归里的return返回!!!
  17. Jetpack-Compose之三附带效应(副作用)
  18. uniapp 小程序 加载显示激励视频广告
  19. 雅虎将面临史上最严重危机:董事会或将解散
  20. 酸爽,最近又帮业务方制作了一个数据看板(附源码)

热门文章

  1. 25亿,周鸿祎为何情定大神
  2. 平方数及其相关思想(SDUT)
  3. 详解RS232/UART/协议/串口通信
  4. 全局监听空格键事件 踩坑
  5. Dolby和DTS分别推出新一代环绕音频格式——DD PLUS DTS HD
  6. 微信免密支付php代码实现,微信刷卡支付接入模式及免密流程
  7. 物资租赁管理系统(MyEclipse+java+SSh+MySQL)
  8. 机器学习 决策树篇——解决连续变量的分类问题
  9. CentOS8系统新特性(2)--dnf代替yum管理软件包
  10. 设计模式 —— 组合模式