分享

玩转VC++系统托盘程序(WIN8)

 king9413 2017-01-22

WINDOWS系统托盘是一个特殊区域,通常在桌面的右下角,也就是任务栏的右边。系统常驻在托盘的程序有时钟,音量控制,输入法,网络状态等。第三方应用如QQ程序也是一个典型的托盘程序,当最小化时企鹅会乖乖的待在屏幕右下角等待主人的呼唤。

    系统托盘的方便之处在于,程序在暂时不用时,将它放到托盘里,随用随叫,不必将其关闭。而QQ在接收到消息后,也会在托盘中闪动提示,十分人性化。

那么如何用VC++来开发托盘程序呢?下面会用一个例子来玩转WINDOWS托盘程序。

首先,定义一下需要的功能。(需求确定)

  1. 程序最小化到托盘。

  2. 右键点击,显示一个菜单。

  3. 鼠标左键双击托盘图标,打开程序。

  4. 程序中点击一个按钮,改变托盘图标。

好了,就这么简单的Demo,下面看看如何实现。

其次,归纳一下用到的技术点。

  1. 托盘相关API

  2. MFC对鼠标操作消息的接收

先来说说托盘相关的APIMFC并没有直接提高便利的类来支持系统托盘编程,我们需要用到SHELLAPI中的Shell_NotifyIcon函数。原型为:

  1. BOOL Shell_NotifyIcon(  
  2.     DWORD dwMessage,  
  3.     PNOTIFYICONDATA lpdata  
  4. );  

函数很简单清晰,只有两个参数。参数一dwMessage用来指定托盘的动作,这是一个四字节的值。如下:

  1. NIM_ADD(0X00000000):添加一个系统托盘

  2. NIM_MODIFY(0X00000001):系统托盘的修改

  3. NIM_DELETE(0X00000002):系统托盘的删除

  4. NIM_SETFOCUS(0X00000003):令系统托盘获得焦点

  5. NIM_SETVERSION(0X00000004):系统托盘设置版本

参数二PNOTIFYICONDATA是专门为此服务的结构体。原型如下:

  1. typedef struct _NOTIFYICONDATA {  
  2.   DWORD cbSize;//结构体的大小,单位是字节  
  3.   HWND  hWnd;//此托盘程序的句柄  
  4.   UINT  uID;// 系统为托盘区域每个图标分配的ID  
  5.   UINT  uFlags;//简单的说,就是一个标示  
  6.   UINT  uCallbackMessage;//回调消息。需要自定义一个消息,用来接收鼠标滑过或点击等消息。  
  7.   HICON hIcon;//图标  
  8.   TCHAR szTip[64];//提示文字的大小  
  9.   DWORD dwState;//图标的状态  
  10.   DWORD dwStateMask;//与上面类似  
  11.   TCHAR szInfo[256];//显示在气泡通知中的文本  
  12.   union {  
  13.     UINT uTimeout;  
  14.     UINT uVersion;  
  15.   };  
  16.   TCHAR szInfoTitle[64];//气泡通知的标题  
  17.   DWORD dwInfoFlags;//修改气泡通知相关的标示  
  18.   GUID  guidItem;//图标的GUID  
  19.   HICON hBalloonIcon;//气泡通知的图标  
  20. } NOTIFYICONDATA, *PNOTIFYICONDATA;  

再来说说MFC中对鼠标操作信息的接收。

其实上面的调查结果一出,这个问题也就迎刃而解了。关键在uCallbackMessage。我们会自定义一个消息,比如就叫做WM_ICON_NOTIFY,当此托盘图标有鼠标滑过,悬停或点击,键盘操作时回调这个接收自定义消息的函数来处理。这一切都被安排好了,我们照着做就可以了。

第三、功能的实现

1.最小化到托盘

创建托盘的函数ToTray

  1. m_tnd.cbSize = sizeof(NOTIFYICONDATA);  
  2. m_tnd.hWnd   = pWnd->GetSafeHwnd();  
  3. m_tnd.uID    = uID;  
  4. m_tnd.hIcon  = icon;  
  5. m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;  
  6. m_tnd.uCallbackMessage = uCallbackMessage;  
  7. strcpy (m_tnd.szTip, szToolTip);  
  8. // Set the tray icon  
  9. Shell_NotifyIcon(NIM_ADD, &m_tnd);  

窗口最小化在OnSysCommand中判断:

  1.     else if (nID == SC_MINIMIZE)  
  2.     {  
  3.         ToTray();  
  4.     ShowWindow(SW_HIDE);//隐藏窗口  
  5. }  

23功能都可以在获得托盘事件函数处理:

  1. LRESULT CTrayIcon::OnTrayNotification(UINT wParam, LONG lParam)   
  2. {  
  3.     //Return quickly if its not for this tray icon  
  4.     if (wParam != m_tnd.uID)  
  5.         return 0L;  
  6.   
  7.     // Clicking with right or left button brings up a context menu  
  8.     if (LOWORD(lParam) == WM_RBUTTONUP /*|| LOWORD(lParam) == WM_LBUTTONUP*/)  
  9.     {     
  10.         //TODO:WHEN RIGHT CLICK,YOUR MENU SHOW HERE  
  11.     }   
  12.     else if (LOWORD(lParam) == WM_LBUTTONDBLCLK)   
  13.     {  
  14.         //TODO:DOUBLE LEFT CLICK,SHOW MAIN WINDOW  
  15.     }  
  16.   
  17.     return 1;  
  18. }  

4.修改图标

这个就比较容易了,直接修改参数即可:

  1. m_tnd.uFlags = NIF_ICON;  
  2. m_tnd.hIcon = hIcon;  
  3.   
  4. Shell_NotifyIcon(NIM_MODIFY, &m_tnd);  

完整的例子请下载demo代码,借用了网上比较流行的封装好的TrayIcon类。

参考:

MSDN上的详细解释:http://msdn.microsoft.com/en-us/library/bb762159(VS.85).aspx

Vckbase:http://www./index.php/cv/122

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多