当前位置: 首页 > 编程日记 > 正文

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 ,关于这个就到这里。

                              拙见,小记!

相关文章:

王海峰发布百度智能云最新架构,推出AI中台和知识中台

5月18日,在百度云智峰会上,百度CTO王海峰发布最新百度智能云架构规划。首先,他分享了百度利用AI、大数据、云计算等技术帮助疫情防控、复工复产的成果:AI多人测温1周检测2700万人次,时空大数据记录人流迁徙24亿人次&am…

Linux虚拟内存优化的方法

首先查看虚拟内存的使用情况,使用命令   # free   查看当前系统的内存使用情况。  一般来说,linux的物理内存几乎是完全used。这个和windows非常大的区别,它的内存管理机制将系统内存充分利用,并非windows无论多大的内存都要…

statpot:使用mongo+bootstrap+highcharts做统计报表

最近做了一个统计项目,这个统计项目大致的需求是统计接口的访问速度。客户端会调用一个接口来记录接口的访问情况,我的需求就需要分析这些数据,然后做出个统计报表。 需求实现 最初的时候想着每天把这些接口访问情况的信息存储到mysql中&…

磁盘文件目录罗列和list控件的使用

开发类似ftp客户端的这种软件,需要对每个磁盘下的文件目录进行罗列并显示。方便文件的上传、下载等。就如同我们打开每个磁盘所显示的那样,罗列了你这个磁盘目录下的所有文件夹和文件。 那我们在自己的程序中如何做到这样呢? 主要用到两个…

潘石屹Python考试成绩99分,网友:还有一分怕你骄傲

整理 | 伍杏玲题图 | 视觉中国来源 | 程序人生(ID:coder_life)5月16日凌晨00:21分,地产大亨潘石屹在微博晒出自己的Python编程一级考试成绩,99分,厉害!像每个学生时期的我们,还会“检…

让Chrome成为你的pdf阅读器

我在Mac OS上使用过的浏览器有Chrome、Safari和Firefox,由于做的产品要支持多浏览器,所以这几种浏览器都会用到,Chrome的使用频率更高一些。 之前想通过浏览器在线阅读PDF时,一般都会提示进行下载,装了类似iGetter或Fo…

l5如何通过路由走api版本回退查找设置

l5如何通过路由走api版本回退查找设置 具体需求 当前遇到的问题是使用laravel写接口,但是接口是有版本号的,我们把版本号放在url中,比如: http://yejianfeng.com/api/user/info/?uid1 http://yejianfeng.com/api1.1/user/info/?…

jspf插件框架

简介:jspf (Java Simple Plugin Framework) 是一个插件框架,用于减少小型项目的的开发时间,增加代码的可维护性。他完全隐藏了组件的详细实现,只用到他们的接口。加载组件所需要的代码也很少,便于编写。jspf框架完全基…

list控件响应鼠标键的单双击

前面一片博客磁盘文件目录罗列和list控件的使用 写过关于list控件的一点使用方法。这篇博客接着继续讲list控件,当我把某个磁盘下的文件目录列出来显示在list控件中,我们肯定是想要对这些目录进行一些操作,比如新建文件夹、删除文件等操作。那…

我佛了!用KNN实现验证码识别,又 Get 到一招!

作者| 李秋键责编| Carol出品| AI科技大本营(ID:rgznai100)头图 | CSDN付费下载自视觉中国验证码使我们生活中最为常见的防治爬虫和机器人登录攻击的手段,一般的验证码主要由数字和字母组成,故我们可以设想&#xff1a…

JVM中的垃圾收集器

2019独角兽企业重金招聘Python工程师标准>>> Serial收集器: 一种新生代的单线程收集器,采用复制算法回收。当它进行垃圾收集时,其他用户的所有线程都将暂停。 Serial Old收集器:Serial的老年代版本,采用的是标记-清除算…

linux系统用户,组和权限的管理

PS: {最近一直在做毕业设计,前面博客也记录过我的一些过程。其中需要在Ubuntu上搭建一个FTP服务器,此处我选择Vsftpd,但是在我对vsftpd的配置文件vsftpd.conf设置正确后(对于上传,下载等设置肯定没问题&am…

520 情人节 :属于Python 程序员的脱单攻略大合集(视频版)

作者| Python 编程时光责编| Carol情人节年年有,但今年的 5.20 要比以往的更有意义。2020.05.20 ,爱你爱你我爱你,如果再卡个时间(13:14),那就是 爱你爱你我爱你一生一世。为了能过上这个这个百年难遇的情人…

使用Word2010灵活掌握文档结构

使用Microsoft Word应用程序组织和编写文档时,可能会出现反复调整文档结构的情况,而通过一系列的剪切、复制、粘贴操作来解决问题,可能会让您觉得很麻烦,有没有更好的解决办法呢?其实,通过使用Word 2010中全…

深入Jetty源码之HTTP协议

在计算机网络中,如果两台机器要通信,他们首先要定义通信数据的格式,这样在服务器收到客户端的请求消息时,它才能正确的解析请求的内容,然后根据请求内容处理逻辑,并将相应消息传递会客户端;此时…

64位win7安装vs2010出现“组件安装失败...”等问题的解决方法

如题,公司发了新电脑,安装的是64位win7 ,我原来的本本安装的是32位的win7,当时安装vs2010的时候并没有那么多事,这次安装却真是让我蛋疼至极。 先后下了3个vs的安装包,中文版的,有专业版的,有旗…

不同网段路由配置

PC1 ip 192.168.1.1PC2 ip 192.168.4.1路由0 f0/0 192.168.1.254 f0/1 192.168.2.1路由1 f0/0 192.168.3.1f0/1 192.168.2.2路由2 f0/0 192.168.4.254 f0/1 192.168.3.2路由器0Router>enRouter#conf tRouter(config)#no ip domain-lookupRouter(config)#line console 0…

黑科技:绕过眼睛植入幻觉,科学家成功在盲人脑海中呈现指定图像!

来源 | 学术头条(ID:SciTouTiao)头图 | CSDN付费下载自视觉中国对于全球 5000 多万盲人来说,重见光明是一个遥不可及的梦想。而为了与盲人朋友进行交互,我们发明了盲文,用各种凸起的字符集合来表达各种意思。但这种通过…

Solr 4.x定时、实时增量索引 - 修改、删除和新增索引

2019独角兽企业重金招聘Python工程师标准>>> 一、开始增量索引前的准备工作。 1、认识data-config.xml中相关属性 <!-- transformer 格式转化&#xff1a;HTMLStripTransforme表示 索引中将忽略HTML标签 ---> <!-- query: 查询数据库表符合记录数据 …

关于Blocking IO, Non-Blocking IO 和 Asynchronous I/O的理解

文章写得很详细很清楚了&#xff0c;对我的理解帮助很大。 转载自&#xff1a;http://www.cnblogs.com/whyandinside/archive/2012/03/04/2379234.html。 概括来说&#xff0c;一个IO操作可以分为两个部分&#xff1a;发出请求、结果完成。如果从发出请求到结果返回&#xff…

还在苦恼机器学习和线性回归?这篇总结拿走不谢 | 原力计划

作者 | 听星的朗瑞责编 | 王晓曼出品 | CSDN博客题图 | 东方IC什么是机器学习&#xff1f;机器学习是一种实现人工智能的方法&#xff0c;从数据中寻找规律、建立关系&#xff0c;根据建立的关系去解决问题&#xff0c;从数据中进行经验学习&#xff0c;实现自我优化与升级。维…

网页设计和用户界面设计

摘要&#xff1a;这是两个现在网页设计领域使用频率非常高的词。在大多数情况下&#xff0c;它们被相互替代。这个领域内外的很多人都认为这是两个意义基本一样的词。但是它们真的可以互相混淆么&#xff1f;这是两个现在网页设计领域使用频率非常高的词。在大多数情况下&#…

使用VisualStudio2010连接CodePlex进行代码管理

摘要&#xff1a;CodePlex是微软的开源工程网站&#xff0c;涉及诸多微软最新技术的开源工程&#xff0c;同时你也可以建立并向世界展示自己的开源工程。同SourceForge、GoogleCode相比CodePlex有其自身的优势&#xff0c;特别是对做.Net开发的朋友来说&#xff0c;由于CodePle…

计算程序运行时间(time_t, clock_t)

转载自&#xff1a;http://blog.chinaunix.net/uid-23208702-id-75182.html 计算程序运行时间&#xff08;time_t, clock_t&#xff09;-whyliyi-ChinaUnix博客 我们有时需要得到程序的运行时间&#xff0c;但我们也要知道&#xff0c;根本不可能精确测量某一个程序运行的确切…

又一年5.20,用Python助力程序员脱单大攻略(视频版)

作者 | 写代码的明哥来源 | Python编程时光&#xff08;ID: Cool-Python&#xff09;情人节年年有&#xff0c;但今年的 5.20 要比以往的更有意义。2020.05.20 &#xff0c;爱你爱你我爱你&#xff0c;如果再卡个时间&#xff08;13:14&#xff09;&#xff0c;那就是 爱你爱你…

pthred()多线程计算派

实验一&#xff1a;计算π问题描述实验提供了两种计算方法&#xff0c;一种使用积分方法&#xff0c;另一种采用随机数方法。本报告中采用积分方法。计算公式&#xff1a;程序流程图&#xff1a;(图1)函数流程图(图2)一组实验数据&#xff0c;计算规模&#xff1a;500,000,000性…

使用最小堆优化Dijkstra算法

OJ5.2很简单&#xff0c;使用priority_queue实现了最小堆竟然都过了OJ……每次遇到relax的问题时都简单粗暴地重新push进一个节点…… 然而正确的实现应该是下面这样的吧&#xff0c;关键在于swap堆中元素时使用pos数组存储改变位置后的编号为k的节点对应在堆中的位置。下面这种…

C语言编程技巧-signal(信号机制)

http://blog.sina.com.cn/s/blog_6a1837e90100v1vc.html

第一课:网络参考模型OSI

网络参考模型OSI(一)&#xff1a;模型提出目的&#xff1a;开放系统互连。使各个厂商的设备可以很好的互连、互通、互操作。(二)&#xff1a;各层功能(1):物理层&#xff1a;负责链路上bit流的传输。&#xff08;bit流显著的特点是&#xff0c;不支持格式或者结构&#xff09;。…

在线直播 | 是事实还是贩卖焦虑?IT行业也偏爱“小鲜肉”​

几年前曾看过这样一篇报道&#xff1a;Java 之父求职被嫌年纪大&#xff0c;硅谷公司现在喜欢“小鲜肉”&#xff0c;不爱“老古董”。Java之父 James Gosling 在 Facebook 上发表了他所遭遇的年龄歧视&#xff1a;我曾在面试的时候被 HR 告知&#xff0c;“通常我们不招你这种…