【WIN32之旅】给托盘图标加上MOUSE_ENTER、MOUSE_HOVER、MOUSE_LEAVE消息
转载请说明原出处,谢谢~ 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 );
}
总而言之,虽然微软没有给我们所需要的检测鼠标进入、移出以及悬停托盘的消息,但只要我们静下心来认真思考仔细分析,我想我们总会会心一笑入浴春风,相信以上的内容能够帮助到正需要帮助的人。
【WIN32之旅】给托盘图标加上MOUSE_ENTER、MOUSE_HOVER、MOUSE_LEAVE消息相关推荐
- 【WIN32之旅】WINDOWS错误处理与参考(四)
转载请说明原出处,谢谢~ http://blog.csdn.net/seven_1992/article/details/44497435 上一篇,我们说到了GetLastError()函数,可是它返 ...
- WIN32下实现输入法所需要的一些必要消息、函数和说明
IME消息 以下列出IME中用到的消息. WM_IME_CHAR(IME得到了转换结果中的一个字符) WM_IME_COMPOSITION(IME根据用户击键的情况更改了按键组合状态) WM_IME_ ...
- Python发送微信消息(文字、图片、文件)给指定好友和微信群(调用Win32 API模拟人的手动操作来发送消息)
本示例是调用Windows API模拟发送,用Python调用win32api这个库来调用Windows API模拟人的手动操作来发送消息. 在使用前,请将你微信的窗口设置为在最前面,这样就便于程序找 ...
- 《C++字符串完全指南——第一部分:win32 字符编码》
<C++字符串完全指南--第一部分:win32 字符编码> 原作者:Michael Dun 译 者:Dingqiao Wang 引言 毫无疑问,你肯定见过像TCHAR, st ...
- 【win32汇编】0x04 第一个窗口程序
第一个win32汇编窗口程序,主要来自 win32汇编语言程序设计,然后加上了自己查阅msdn文档的一些理解,基本过程: start入口地址 --> _WinMain主函数 --> 定义一 ...
- 利用Python和win32编程范例——按需定制一个按键精灵
转自:作者 橘子一方 http://www.orangecube.net/articles/python-win32-example.html 利用Python和win32编程范例--按需定制一个按键 ...
- win32汇编使用win32 api实现字符串拷贝
字符串拷贝,调用win32的lstrcpy函数:拷贝了以后用消息框显示一下: .386 .model flat, stdcall option casemap :noneinclude S:\masm ...
- 图解Dev C++ 创建Win32 项目模板
打开Dev C++,新建一个项目: 在Windows程序设计第五版源码中,找到第10章,PoePoem例子:把PoePoem.c代码拷贝到main.cpp中: 用它来作为一个模板:PoePoem.c比 ...
- win32开发(简单绘图)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 在win32上面,所有的操作都是通过消息来完成的.正如前面一节说的那样,WM_CREATE.WM ...
最新文章
- mysql执行事务的语句_详解MySQL执行事务的语法和流程
- java架构师,必须掌握的几点技术?
- linux上通过lighttpd上跑一个C语言的CGI小页面以及所遇到的坑
- Cordova 本地项目创建方法
- JSON.stringify()中文乱码
- 程序员的数学笔记3--迭代法
- linux 命令行 播放器,Linux下基于命令行的音乐播放器
- Django Celerybeat日志报错处理('NoneType' object has no attribute 'is_due')
- 使用qBittorrent下载bt种子文件
- Openstack 虚拟机通讯
- kvaser canking 的使用
- 线程安全的随机数生成
- matlab如何表示冲激信号,matlab里如何表示冲激信号
- openfire主要插件介绍
- linux系统下的程序开发报告册,linux系统及其应用(应用开发)实验报告册.doc
- 说一说递归里的return返回!!!
- Jetpack-Compose之三附带效应(副作用)
- uniapp 小程序 加载显示激励视频广告
- 雅虎将面临史上最严重危机:董事会或将解散
- 酸爽,最近又帮业务方制作了一个数据看板(附源码)