IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

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

    lincyang发表于 2014-05-14 15:34:33
    love 0
    

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

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

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

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

    1. 程序最小化到托盘。

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

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

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

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

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

    1. 托盘相关API

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

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

    BOOL Shell_NotifyIcon(
        DWORD dwMessage,
        PNOTIFYICONDATA lpdata
    );
    

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

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

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

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

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

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

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

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

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

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

    第三、功能的实现

    1.最小化到托盘

    创建托盘的函数ToTray:

    	m_tnd.cbSize = sizeof(NOTIFYICONDATA);
    	m_tnd.hWnd	 = pWnd->GetSafeHwnd();
    	m_tnd.uID	 = uID;
    	m_tnd.hIcon  = icon;
    	m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
    	m_tnd.uCallbackMessage = uCallbackMessage;
    	strcpy (m_tnd.szTip, szToolTip);
    	// Set the tray icon
    	Shell_NotifyIcon(NIM_ADD, &m_tnd);
    

    窗口最小化在OnSysCommand中判断:

        else if (nID == SC_MINIMIZE)
        {
            ToTray();
    	ShowWindow(SW_HIDE);//隐藏窗口
    }
    

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

    LRESULT CTrayIcon::OnTrayNotification(UINT wParam, LONG lParam) 
    {
    	//Return quickly if its not for this tray icon
    	if (wParam != m_tnd.uID)
    		return 0L;
    
    	// Clicking with right or left button brings up a context menu
    	if (LOWORD(lParam) == WM_RBUTTONUP /*|| LOWORD(lParam) == WM_LBUTTONUP*/)
    	{	
    		//TODO:WHEN RIGHT CLICK,YOUR MENU SHOW HERE
    	} 
    	else if (LOWORD(lParam) == WM_LBUTTONDBLCLK) 
    	{
    		//TODO:DOUBLE LEFT CLICK,SHOW MAIN WINDOW
    	}
    
    	return 1;
    }
    

    4.修改图标

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

    	m_tnd.uFlags = NIF_ICON;
    	m_tnd.hIcon = hIcon;
    
    	Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
    

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

    参考:

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

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

     







沪ICP备19023445号-2号
友情链接