首先,必须知道一个结构体NOTIFYICONDATA ,这是MFC中包含系统需要的用来传递托盘区域消息的信息结构体,有了它,我们今
天的任务就完全可以轻松完成了!这时候,我们可以在我们的类中申明一个NOTIFYICONDATA的成员变量为m_nid。
接下来,我们可以给这个结构体变量赋我们想要的值了,记住赋值语句要写在OnInitDialog初始化窗口函数里,不要写在构造函 数中,否则将会无效。m_nid.cbSize = sizeof( NOTIFYICONDATA );m_nid.hWnd = m_hWnd; m_nid.uID = IDR_MAINFRAME; m_nid.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;m_nid.uCallbackMessage = WM_SYSTEMTRAY; //自定义消息m_nid.hIcon = m_hIcon; strcpy(m_nid.szTip, "认证系统客户端");::Shell_NotifyIcon(NIM_ADD, &m_nid);然后,让我们一句句的解析这段代码,m_nid.cbSize = sizeof( NOTIFYICONDATA );cbSize表示结构体的大小,以字节未单位,这里赋值了NOTIFYICONDATA的结构体标准大小就行了,用sizeof函数就能获得其字节 大小m_nid.hWnd = m_hWnd; hWnd是你想要赋予托盘的窗口句柄,MFC的窗口类中因为都是继承CDialog类,所以其中会有一个成员变量是m_hWnd保存着当前实 例窗口的具体句柄,我们将其赋值给它就行了m_nid.uID = IDR_MAINFRAME; uID指的是应用程序定义的任务栏图标的标识符,简单的时候就是图片图标的ID,这里的ID你可以进入工程下的ResourceView中 找到Icon文件夹下的图标,里面的ID号就是我们现在要赋值的具体ID,Shell_NotifyIcon函数调用时,hWnd和UID成员用来标示 具体要操作的图标,可以通过多次的调用,来实现不同uID将多个图标关联到一个窗口hWnd上,从而实现托盘图标切换的效果m_nid.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;uFlags表明具体哪些其他成员为合法数据,简单的说就是只有在uFlags中提到过的变量,才能发挥其作用,具体uFlags可以由以 下一些成员组合:NIF_ICON 表示hicon成员起作用。NIF_MESSAGE 表示uCallbackMessage成员起作用NIF_TIP 表示szTip成员起作用当然还有许多别的如:NIF_STATE,NIF_INFO,NIF_GUID,这里就具体先介绍上面三个,其他想了解的话可以具体查msdnm_nid.uCallbackMessage = WM_SYSTEMTRAY; uCallbackMessage是应用程序定义的消息标示,当鼠标在托盘鼠标上点击事件的时候,程序的WM_SYSTEMTRAY就会被发出,我们只 要在WindowProc函数中就能获得的该消息,从而做出事件响应,如下: switch(message){ case WM_SYSTEMTRAY: //自定义消息 //具体响应消息 break; }其中,大家可以看出WM_SYSTEMTRAY不是系统消息,而是自定义的一个消息,用于表示这个特殊的事件发生了,至于怎么定义呢 ,就是用宏了#define WM_SYSTEMTRAY WM_USER+1这里解释下,为什么WM_SYSTEMTRAY要宏定义成WM_USER+1呢,据我了解WM_USER是系统消息中的最后一个,也就是说这样定义就 不会和系统的消息冲突成一个同样的值m_nid.hIcon = m_hIcon; 增加、修改或删除的图片句柄,用于控制托盘的图标,m_hIcon是自定义的一个窗口图标句柄HICON m_hIcon;m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);当然你可以直接将m_nid.hIcon = m_hIcon 改成 m_nid.hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME)strcpy(m_nid.szTip, "认证系统客户端");szTip是一个字符串指针,是在鼠标放在图标上的时候,会出现的提示消息。::Shell_NotifyIcon(NIM_ADD, &m_nid);最后一个是一个全局函数 BOOL Shell_NotifyIcon(DWORD dwMessage,PNOTIFYICONDATA ipdata);参数dwMessage表示要执行的操作,可选值为:NIM_ADD 表示在托盘区域增加图标NIM_DELETE 表示删除托盘区域的图标NIM_MODIFY 表示修改托盘区域的图标NIM_SETFOCUS 表示聚焦到托盘图标上第二个参数就是我们上面介绍过的NOTIFYICONDATA结构体的指针了。如果操作成功函数会返回TRUE,否则返回FALSE。///
OK,托盘的实现就是这么简单的啦,但是如果你想具体深入了解,可以查看MSDN里面具体的解释,也可以跟本人沟通下面介绍下应用,具体的应用情况很多。我们就来简单的讲一下,怎么实现窗口隐藏后,双击托盘使窗口再出现,和右击托盘出现退出窗口的实现上面叫到了自定义的消息,在WindowProc函数中,我们可以具体实现switch(message){ case WM_SYSTEMTRAY: //自定义消息 if (lParam == WM_LBUTTONDBLCLK){ ShowWindow(SW_SHOWNORMAL);} break; }上面的代码就实现了,双击托盘实现显示窗口的代码,非常简单,我们就不具体剖析了。要实现右击托盘显示弹出窗口,我们必须先在资源中创建一个菜单,然后加入以下代码 case WM_SYSTEMTRAY: //自定义消息 if (lParam == WM_RBUTTONDOWN){ //右击弹出托盘菜单CMenu menu;menu.LoadMenu(IDR_MENU1);CMenu *pPopUp=menu.GetSubMenu(0);CPoint pt; GetCursorPos(&pt);SetForegroundWindow();
pPopUp->TrackPopupMenu(TPM_RIGHTBUTTON,pt.x,pt.y,this); PostMessage(WM_NULL,0,0);}break;代码中,刚开始定义了一个CMenu的对象,然后将我们之前创建的菜单ID加载进去,然后获得鼠标当前的位置,在这个位置上将 菜单显示出来最后退出要删除图标: Shell_NotifyIcon(NIM_DELETE,&m_traydata);