MFC系统托盘的实现
通常电脑里边的软件,当你打开后会在电脑最右下角的任务栏上生成一个系统托盘,当你点击最小化或者点击关闭按钮后,若想恢复窗口,可以左键双击或者单机这个系统图标,同时鼠标右键点击,又会有其他的菜单弹出,比如退出。
我看着感觉还是挺酷炫的,所以打算也在我的程序里边添加一个这样的功能。下边我把我自己探索的过程记录一下:
首先,我们需要用到NOTIFYICONDATA类,它是我们实现系统托盘的核心。关于这个类,百度百科上是这么说的:NOTIFYICONDATA是一个函数公式,主要含义和作用是以此函数用来向任务栏托盘区域发送消息。好了,其他的就不用管了,接下来进行实际的操作。
1、声明一个NOTIFYICONDATA类对象,一般可以放在父类里边作为成员变量或者作为全局的变量。
private:NOTIFYICONDATA NotifyIcon; //系统托盘类
2、自定义一个消息
#define WM_SYSTEMTRAY WM_USER+5
为什么是 WM_USER+5?关于消息WM_USER,为了防止用户定义的消息ID与系统的消息ID冲突,MS(Microsoft)定义了一个宏WM_USER,小于WM_USER的ID被系统使用,大于WM_USER的ID被用户使用。加5是我自己随便定义的,当然你可以自己指定具体的数值。
3、接下来这步,可以自己手动添加,也可以通过类向导来操作。我采用手动添加方式。声明一个响应函数,用来响应鼠标的操作。
protected:afx_msg LRESULT OnSystemtray(WPARAM wParam, LPARAM lParam);
4、注册刚才自定义的消息。在BEGIN_MESSAGE_MAP(CMyPlayerDlg, CDialogEx)和END_MESSAGE_MAP()之间添加如下代码:
ON_MESSAGE(WM_SYSTEMTRAY, &CMyPlayerDlg::OnSystemtray)
5、然后这一步就是开始产生作用的操作。一般添加在Oninitdialog()中,但是也可以是其他的函数中,比如只有在你点击关闭按钮后才添加系统拖盘图标,那么就不是在此处添加,具体在哪里添加,后面我会讲到。
BOOL CMyPlayerDlg::OnInitDialog()
{//设置系统托盘NotifyIcon.cbSize=sizeof(NOTIFYICONDATA);//NotifyIcon.hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);NotifyIcon.hIcon=m_hIcon; //上面那句也可以NotifyIcon.hWnd=m_hWnd;lstrcpy(NotifyIcon.szTip,_T("爆疯牛逼一代"));NotifyIcon.uCallbackMessage=WM_SYSTEMTRAY;NotifyIcon.uFlags=NIF_ICON | NIF_MESSAGE | NIF_TIP;Shell_NotifyIcon(NIM_ADD,&NotifyIcon); //添加系统托盘//...}
其中比较重要的函数是Shell_NotifyIcon(NIM_ADD,&NotifyIcon),关于这个函数的具体解释,可以看这里:http://www.cnblogs.com/duzouzhe/archive/2010/04/08/1707050.html
NIM_ADD参数表示添加一个图标到系统托盘区。
6、上面我们定义了响应函数afx_msg LRESULT OnSystemtray(WPARAM wParam, LPARAM lParam),那么具体如何响应鼠标左键和右键的操作呢?
直接上代码:
afx_msg LRESULT CMyPlayerDlg::OnSystemtray(WPARAM wParam, LPARAM lParam)
{//wParam接收的是图标的ID,而lParam接收的是鼠标的行为
// if(wParam!=IDR_MAINFRAME)
// return 1; switch(lParam) { case WM_RBUTTONDOWN://右键起来时弹出快捷菜单{ CMenu menuexit;//menu.LoadMenuW(IDR_MENU1);//加载菜单资源menuexit.LoadMenuA(IDR_MENUexit);CMenu *pPopup=menuexit.GetSubMenu(0);CPoint mypoint;GetCursorPos(&mypoint);//ClientToScreen(&mypoint);//将客户区坐标转换为屏幕坐标SetForegroundWindow(); PostMessage(WM_NULL,0,0);//显示右键菜单,由视类窗口拥有。pPopup->TrackPopupMenu(TPM_LEFTALIGN,mypoint.x,mypoint.y,this); } break; case WM_LBUTTONDOWN://左键单击的处理 { ModifyStyleEx(0,WS_EX_TOPMOST); //可以改变窗口的显示风格ShowWindow(SW_SHOWNORMAL); } break; } return 0;
}
代码中我只实现了两个消息的响应,即鼠标左键单击和右键单击的消息。当鼠标左键单击后,恢复原窗口的大小和位置;当鼠标右键单击后,弹出菜单。我自己的菜单是如下设置的:
case WM_LBUTTONDOWN:里边的代码没有什么好讲的,关于case WM_RBUTTONDOWN:里边的代码,其实也没什么好讲的,也就是当鼠标右键单击时,装载一个右键菜单而已,其他的没有什么。具体可以看我之前的博客: 右键弹出菜单和快捷键的设置 。
然后菜单里的每一个子菜单的响应函数记得要编写,但先预留退出子菜单我下面讲。
7、其实上面的几部就已经可以实现想要的效果了。但是如果想要点击关闭按钮后程序并不关闭,而只是以系统托盘的形式出现在托盘区,直到你鼠标右键点击图标,执行退出操作,才真正退出,另一方面当你点击最小化后,程序最小化,但任务栏上任然具有程序的图标。如果想要实现这样的效果,其实也很简单,我们需要重写关闭“X”的响应函数。
具体重写的操作我就不写了,之前的博客写过这样的过程。重写代码如下:
void CMyPlayerDlg::OnCancel() //点击X 按钮,最小化到系统托盘
{// TODO: 在此添加专用代码和/或调用基类this->ShowWindow(HIDE_WINDOW);//CDialogEx::OnCancel();
}
注意,注意,上面代码中的CDialogEx::OnCancel();一定要注释掉。因为我们只是想改写关闭操作,但并不真的执行关闭操作,也就是说我们只是想重写关闭按钮操作的响应函数。
但是,如果这样操作以后,你运行会发现,程序关不了了,因为关闭按钮只是执行隐藏窗口功能,你的右键菜单的退出操作也还没写,那怎么办,先杀了这个进程,接着编写如下的步骤。
(关于第5步提到的如果只是想在点击关闭按钮的时候才添加系统托盘,那也应该再OnCancel函数中书写第5步的代码,同时书写this->ShowWindow(HIDE_WINDOW);)
8、关于窗口的关闭过程,我前面的博客里边也记录过,此处就不多说了 。窗口关闭的过程中会执行DestroyWindow()函数,那么我们也将重写这个函数。
BOOL CMyPlayerDlg::DestroyWindow()
{// TODO: 在此添加专用代码和/或调用基类Shell_NotifyIcon(NIM_DELETE, &NotifyIcon);//消除托盘图标return CDialogEx::DestroyWindow();
}
其中Shell_NotifyIcon(NIM_DELETE, &NotifyIcon);//消除托盘图标很关键,正好和之前的Shell_NotifyIcon(NIM_ADD,&NotifyIcon)对应起来了。一个是添加,一个是删除。如果不写Shell_NotifyIcon(NIM_DELETE, &NotifyIcon),当你程序退出后,在系统托盘区的图标还会存在,因为进程残留,需要你鼠标移上去才会消失。
那么我们还需要在子菜单退出的响应函数中调用DestroyWindow()函数。
void CMyPlayerDlg::Onexit()
{// TODO: 在此添加命令处理程序代码DestroyWindow();
}
到此,我们就实现了一个比较满意的系统托盘方案,当然我自己探索的时候,还是碰到了 一些问题的,比如如何执行关闭操作,如何调用退出函数等等。但是,都一一克服了,仔细想想,其实也蛮简单的。
ok ,关于这个就到这里。
拙见,小记!
MFC系统托盘的实现相关推荐
- MFC最小化到系统托盘
在VC++中,想实现将MFC最小化到系统托盘,需要调用NOTIFYICONDATA类,并注册相应的消息,以下详细讲解如何实现: 第一步,声明一个NOTIFYICONDATA类,也就是NOTIFYICO ...
- MFC中将窗口最小化到系统托盘和还原
通过以下步骤可以在MFC程序中将窗口最小化到系统托盘,和还原成窗口,附加代码中如有特殊说明则会用红色标出. 1.添加一个ICON图标,其ID为IDI_ICON_TESTICON,在VS2008坐标的R ...
- MFC小笔记:系统托盘实现
一.需求 本文实现程序系统托盘. 二.界面 主界面为对话框,有最小化.最大化.关闭等功能. 三.原理 利用系统托盘类NOTIFYICONDATA,响应自定义消息,处理托盘鼠标事件. 四.编码 4.1 ...
- delphi 关闭时缩小到托盘_delphi 实现最小化系统托盘
1.new -->application 2.在form1中加入一个tPopMenu 命名为pm1 3.uses ShellAPI; 4.定义一个常量在 const WM_TRAYMSG = W ...
- VC6系统托盘类|崩溃自动重建图标|HOOK窗口消息|气泡效果更新SDK
解决制作托盘气泡提示中遇到的'NIF_INFO' : undeclared identifier VC6下实现托盘气泡提示的关键是要更新SDK,实际上应该就是要更新SHELLAPI.h,SHELL32 ...
- windows系统托盘及托盘菜单
window系统托盘及托盘菜单 下面是一个MFC写的wifi助手程序用于实现系统托盘的代码片段 void CWiFiAssistantDlg::OnClose() { // TODO: 在此添加消息 ...
- 在 Ubuntu Natty 中解除系统托盘限制
在 Ubuntu 11.04 Natty 中,Ubuntu 对顶部面板右上角的通知区域(系统托盘)采用了白名单制度,只有支持 Indicators 并位于白名单的部分程序才会被显示在系统托盘中,目前支 ...
- TrayIcon 类 添加系统托盘不显示托盘图标
为什么80%的码农都做不了架构师?>>> 好久不碰 java swing最近写了一个swing 程序 添加托盘时,怎么也不显示图标,就一空白 ,在网上搜了老半天,大部无效. 边 ...
- 将 VMware 最小化到系统托盘
1, 下载 Trayconizer 官网地址: http://www.whitsoftdev.com/trayconizer/ 下载地址: http://www.whitsoftdev.com/fil ...
最新文章
- android 循环平移动画
- Codeforces Round #698 (Div. 2) D. Nezzar and Board(一步步推出来,超级清晰,不猜结论,看不懂来打我 ~ 好题 )
- [3/18]Windows Server 2008 服务器配置之一DNS
- 【内核】linux内核启动流程详细分析
- spring jdbc设计与实现
- java 循环关键字_Java循环结构_常量_关键字
- 轻松简单地开发Web Services 2
- 史上最强大型分布式架构详解:高并发+数据库+缓存+分布式+微服务+秒杀
- 使用wireshark对HTTPS解密
- 学计算机编程笔记本电脑推荐,想选一款笔记本电脑,主要用来学编程,有什么好的推荐吗?...
- STM32学习——矩阵键盘
- 讯飞tts语音引擎_讯飞iFLYOS语音让家居产品更智能
- p9plus升级鸿蒙,华为P9 Plus(VIE-AL10 EMUI 8.0)手机完美获取root教程,最强root工具,亲测可用!...
- 点亮LED灯及IAR调试
- red hat linux 9下载地址,Red Hat Linux 9.0 ISO下载 (转)
- 龙ol服务器维护补偿boss,《龙OL》12月17日更新公告
- ESP-MQTT-AT指令连接阿里云物联网平台
- 控制windows 8,win8.1 win10 虚拟键盘
- putty 报错no supported authentication methods available (server sent:publickey...)
- MySQL多表查询练习题
热门文章
- xuanke java_wangshangxuankexitong - WEB源码|JSP源码/Java|源代码 - 源码中国
- Window10 VS17下 Opencv3.4.5配置
- 【开源分享】VIDO-SLAM:一种视觉惯性动态物体SLAM系统
- PCL之C++动态内存学习
- 设置VSCode代码编辑器右侧的Minimap代码缩略图滚动条切换显示、隐藏的快捷键Alt+M
- 在Ubuntu 14.04 64bit上为Sublime text 3安装搜狗拼音输入法
- Blender与UE5完美结合全流程创作游戏资产视频教程
- Linux命令之top
- getURLParameters - 网址参数
- w3cscholl的在线代码编辑工具