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

转载于:https://www.cnblogs.com/cwj976277916/p/9115545.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值