在Windows操作系统中任务栏的右边(托盘)会常驻几个图标如输入法切换图标音量控制图标等此外我们还经常遇到具有托盘图标的软件如金山词霸实时监测功能的杀毒软件等这些软件在后台运行通常不占用太多的屏幕资源只在通知栏上放一个小小的标志必要时我们可以通过用鼠标点击图标对其进行选单操作或激活其主窗口有时我们自己编写的程序也希望有类似的效果本文将详细地介绍用VC设计托盘图标程序的方法 一 NOTIFYICONDATA结构 NOTIFYICONDATA结构包含了系统用来处理托盘图标的信息它包括选择的图标回调消息提示消息和图标对应的窗口等内容其定义为 typedef struct—NOTIFYICONDATA { DWORD cbSize; //以字节为单位的这个结构的大小 HWND hWnd; //接收托盘图标通知消息的窗口句柄 UINT uID; //应用程序定义的该图标的ID号 UINT uFlags; //设置该图标的属性 UINT uCallbackMessage; //应用程序定义的消息ID号此消息传递给hWnd HICON hIcon; //图标的句柄 char szTip[]; //鼠标停留在图标上显示的提示信息 } NOTIFYICONDATA ?PNOTIFYICONDATA; 该结构中成员uFlags可以是下列的组合或其中之一 NIF_ICON设置成员hIcon有效 NIF_MESSAGE设置成员uCallbackMessage有效 NIF_TIP设置成员szTip有效 二 Shell_NotifyIcon函数 全局函数Shell_NotifyIcon()用于在托盘上增加删除或修改图标其原型为 WINSHELLAPI BOOL WINAPI Shell_NotifyIcon( DWORD dwMessagePNOTIFYICONDATA pnid); Pnid是上面的NOTIFYICONDATA结构的指针 dwMessage是被传递的消息可以是以下消息之一 NIM_ADD增加图标 NIM_DELETE删除图标 NIM_MODIFY修改图标 三 托盘图标程序设计示例 首先我们用AppWizard创建一个不基于文档和视图结构的应用程序Tray我们并不想在应用程序启动时显示主窗口所以需要删除应用程序类CTrayApp中成员函数InitInstance()的以下两句代码 pFrame〉ActivateFrame(); pFrame〉ShowWindow(SW_SHOW); 在CMainFrame类中加入NOTIFYICONDATA结构的保护成员变量m_tnid并在其OnCreate函数中return语句前加入生成托盘图标的代码 m_tnidcbSize=sizeof(NOTIFYICONDATA); m_tnidhWnd=this〉m_hWnd; m_tniduFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP; m_tniduCallbackMessage=MYWM_NOTIFYICON; //用户定义的回调消息 CString szToolTip; szToolTip=_T(托盘图标实例); _tcscpy(m_tnidszTip szToolTip); m_tniduID=IDR_MAINFRAME; HICON hIcon; hIcon=AfxGetApp()〉LoadIcon(IDR_MAINFRAME); m_tnidhIcon=hIcon; ::Shell_NotifyIcon(NIM_ADD&&m_tnid); if(hIcon)::DestroyIcon(hIcon); 返回消息的ID应在主框架类的头函数中定义 #define MYWM_NOTIFYICON WM_USER+ 为了处理图标返回消息如鼠标左键双击鼠标右键单击消息我们重载WindowProc()函数此外我们还希望在主框架窗口最小化时图标不在任务栏的空白区出现在此函数中同时作相应处理 LRESULT CMainFrame::WindowProc(UINT message WPARAM wParam LPARAM lParam) { switch(message){ case MYWM_NOTIFYICON: //如果是用户定义的消息 if(lParam==WM_LBUTTONDBLCLK){ //鼠标双击时主窗口出现 AfxGetApp()〉m_pMainWnd〉ShowWindow(SW_SHOW); } else if(lParam==WM_RBUTTONDOWN){ //鼠标右键单击弹出选单 CMenu menu; menuLoadMenu(IDR_RIGHT_MENU); //载入事先定义的选单 CMenu?pMenu=menuGetSubMenu(); CPoint pos; GetCursorPos(&&pos); pMenu〉TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTONposxposyAfxGetMainWnd()); } break; case WM_SYSCOMMAND: //如果是系统消息 if(wParam= =SC_MINIMIZE){ //接收到最小化消息时主窗口隐藏 AfxGetApp()〉m_pMainWnd〉ShowWindow(SW_HIDE); return ; } break; } return CFrameWnd::WindowProc(message wParam lParam); } 为使应用程序退出时图标消失映射WM_DESTROY消息在OnDestroy()函数中加入 ::Shell_NotifyIcon(NIM_DELETE&&m_tnid); 至此托盘图标程序的常规功能我们均已实现我们还可以通过Shell_NotifyIcon()函数的调用实现不同状态下图标的改变 本程序在VC++ Windows / Professional下调试通过 |