MFC程序添加通知区域图标

给MFC程序添加通知区域图标

 

       现在起来越多的程序都有一个通知区域图标(托盘图标),既美观又方便。但是MFC不像C#一样提供NotifyIcon控件,要实现通知区域图标,就要自己做一个CTrayIcon类或者使用NOTIFYICONDATA结构。
       MSDN中关于NOTIFYICONDATA的介绍:
       http://msdn.microsoft.com/en-us/library/ms910625.aspx
       我在这里记录一下自己通过NOTIFYICONDATA实现MFC程序中的通知区域图标的过程,既是分享,也方便以后自己查阅。


       1. 在CMainFrame类(或者是CXxxDlg类)中添加一个NOTIFYICONDATA的结构体变量:
           NOTIFYICONDATA m_ntIcon;


        并在CMainFrame的OnCreate函数中(或者是OnInitDialog)设置该变量:
           m_ntIcon.cbSize = sizeof(NOTIFYICONDATA);                            //该结构体变量的大小
           m_ntIcon.hIcon = AfxGetApp()->LoadIconA(IDR_MAINFRAME);  //图标,通过资源ID得到
           m_ntIcon.hWnd = this->m_hWnd;                                                 //接收托盘图标通知消息的窗口句柄
           char atip[128] = "a notify icon";                                                     //鼠标设上面时显示的提示
           strcpy_s(m_ntIcon.szTip, 128, atip);             
           m_ntIcon.uCallbackMessage = MY_WM_NOTIFYICON;                //应用程序定义的消息ID号
           m_ntIcon.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;               //图标的属性:设置成员uCallbackMessage、hIcon、szTip有效
          ::Shell_NotifyIconA(NIM_ADD, &m_ntIcon);                                 //在系统通知区域增加这个图标

 

       2. 为这个图标添加消息处理
       (1)定义回调消息的ID
           #define MY_WM_NOTIFYICON (WM_USER+1001)


       (2)添加消息映射
           BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)     

               //OnNotifyIcon 就是消息处理函数的名称

               ON_MESSAGE(MY_WM_NOTIFYICON, &CMainFrame::OnNotifyIcon)             
         END_MESSAGE_MAP()


       (3)在CMainFrame类(或者是CXxxDlg类)中添加该图标的消息处理函数
          .h文件中:
             public:
                 afx_msg LRESULT OnNotifyIcon(WPARAM, LPARAM);
          .cpp文件中:
                 LRESULT CMainFrame::OnNotifyIcon(WPARAM wparam, LPARAM lparam)
                {
                    if(lparam == WM_LBUTTONDOWN)
                    {
                         //这里添加对鼠标左键点击的处理,具体处理见(4)
                    }
                    else if(lparam == WM_RBUTTONDOWN)
                   {
                        //这里添加对鼠标右键点击的处理,具体处理见(5)
                    }
                    return 0;
                 }


       (4)对鼠标左键点击的处理:
         我一般的处理是如果窗口是正常显示的,点一下将窗口最小化到系统托盘;如果窗口是最小化的,点一下则将其恢复到正常显示。  
         这里我通过一个bool成员变量m_bMin来判断当前窗口的状态
         //恢复窗口或者最小化
         if(m_bMin == true)
         {
              AfxGetMainWnd()->ShowWindow(SW_SHOW);
              AfxGetMainWnd()->ShowWindow(SW_RESTORE);
              //这里貌似只有写这样两句才能保证恢复窗口后,该窗口处于活动状态(在最前面)
              m_bMin = false;
         }
         else
         {
              AfxGetMainWnd()->ShowWindow(SW_MINIMIZE);
              m_bMin = true;
          
         其中m_bMin的值,可以在OnSize(UINT nType, int cx, int cy)中进行设定,如果nType为SIZE_MINIMIZED时,将其设为true;其它则设为fasle。具体代码就不在这里写了。
  
       (5)对鼠标右键点击的处理:
          我一般是鼠标右键点击,则弹出一个右键菜单:
          //弹出左键菜单
         CMenu popMenu;
         popMenu.LoadMenuA(IDR_MENU_POPUP);   //IDR_MENU_POPUP是在ResourceView中创建并编辑的一个菜单
         CMenu* pmenu = popMenu.GetSubMenu(0);   //弹出的菜单实际上是IDR_MENU_POPUP菜单的某项的子菜单,这里是第一项
        CPoint pos;
        GetCursorPos(&pos);            //弹出菜单的位置,这里就是鼠标的当前位置
        //显示该菜单,第一个参数的两个值分别表示在鼠标的右边显示、响应鼠标右击
        pmenu->TrackPopupMenu(TPM_RIGHTALIGN|TPM_RIGHTBUTTON, pos.x, pos.y, AfxGetMainWnd(), 0);  
        对于这个菜单的项及其处理,写在后面。
  
      3. 程序退出时,删除该图标
      这一步一定不能没有,不然的话,程序退出后,通知区域还有这个图标,只有鼠标放上去后才会消失。
      在OnDestroy()函数里面:
      //删除该图标
      ::Shell_NotifyIcon(NIM_DELETE, &m_ntIcon);
  
      4. 关于弹出的右键菜单
       我做的简单的右键菜单包含”显示窗口“,”关于...“和”退出“,可以在ResuourceView中,对该菜单添加消息处理函数。
       (1)显示窗口
        点这个菜单,这显示程序的主窗口,消息处理函数如下:
        void CMainFrame::OnPopupShow()
       {
            // TODO: Add your command handler code here
            AfxGetMainWnd()->ShowWindow(SW_SHOWNORMAL );
       }


      (2)关于...
        弹出一个”关于“对话框:
        void CMainFrame::OnPopupAbout()
       {
           // TODO: Add your command handler code here
           CAboutDlg abdlg;
           abdlg.DoModal();
       }


      (3)退出
       发送一个WM_CLOSE消息,关闭窗口
       void CMainFrame::OnPopupQuit()
      {
           // TODO: Add your command handler code here
           SendMessage(WM_CLOSE);
       }
      这里要注意的是:如果主窗口的关闭按钮点击后,不是退出程序,而是最小化到系统托盘(现在越来越多的程序是这样了,可以在OnClose()函数中实现),就不能通过
       SendMessage(WM_CLOSE);
       来关闭窗口了。我用的方法是 
       this->DestroyWindow();
       但不确定这个方法是否合适。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值