VC里面要添加托盘图标和托盘菜单,大概过程:
MSDN中介绍的结构体:
typedef struct _NOTIFYICONDATA { DWORD cbSize;//结构体的大小 HWND hWnd;//窗口句柄 UINT uID;//图标关联的ID,需要和多个托盘图标关联时用到 UINT uFlags;//标识,表明该托盘图标需要修改的内容,如图标,提示,状态等 UINT uCallbackMessage;//自定义回调消息 HICON hIcon;//图标 TCHAR szTip[64];//鼠标指着图标时的提示信息 DWORD dwState;//图标状态 DWORD dwStateMask;//指明dwState成员的那些位可以被设置或者访问 TCHAR szInfo[256];//气球提示内容 union { UINT uTimeout;//气球提示的超时时间 UINT uVersion;//版本,用于Windows95和2000风格的图标消息接口 }; TCHAR szInfoTitle[64];//气球提示的标题 DWORD dwInfoFlags;//气球提示的图标 GUID guidItem;//保留 HICON hBalloonIcon;//气球提示的图标,VISTA以上使用 } NOTIFYICONDATA, *PNOTIFYICONDATA;
1. 先添加一个成员变量 NOTIFYICONDATA m_NotiIcon;
2.定义自定义一个消息: #define WM_MY_TRAY_NOTIFICATION WM_USER+100
3 .声明消息处理函数; LRESULT OnNotifyIcon(WPARAM wParam, LPARAM lParam);
4.将消息与消息处理函数联系起来: ON_MESSAGE(WM_MY_TRAY_NOTIFICATION,OnTrayNotification)
5. 实现消息处理:
LRESULT CW620Dlg::OnTrayNotification(WPARAM uID,LPARAM lEvent) { if (uID!=m_NotiIcon.uID || (lEvent!=WM_RBUTTONUP && lEvent!=WM_LBUTTONDBLCLK)) return 0; // If there's a resource menu with the same ID as the icon, use it as // the right-button popup menu. CTrayIcon will interprets the first // item in the menu as the default command for WM_LBUTTONDBLCLK // CMenu menu; if (!menu.LoadMenu(IDR_MENUICON)) return 0; CMenu* pSubMenu = menu.GetSubMenu(0); if (!pSubMenu) return 0; if (lEvent==WM_RBUTTONUP) { // Make first menu item the default (bold font) ::SetMenuDefaultItem(pSubMenu->m_hMenu, 0, TRUE); // Display the menu at the current mouse location. There's a "bug" // (Microsoft calls it a feature) in Windows 95 that requires calling // SetForegroundWindow. To find out more, search for Q135788 in MSDN. // CPoint mouse; GetCursorPos(&mouse); ::SetForegroundWindow(m_NotiIcon.hWnd); ::TrackPopupMenu(pSubMenu->m_hMenu, 0, mouse.x, mouse.y, 0, m_NotiIcon.hWnd, NULL); } else // double click: execute first menu item ::SendMessage(m_NotiIcon.hWnd, WM_COMMAND, pSubMenu->GetMenuItemID(0), 0); return 1; // handled }
6. 添加托盘图标;
在你需要实现托盘的地方添加托盘
BOOL CW620Dlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here ////////////////////////////////////////////////////////////// /* Set the min tray ICON */ //托盘结构体成员初始化 m_NotiIcon.cbSize=sizeof(NOTIFYICONDATA); m_NotiIcon.hWnd=this->m_hWnd; m_NotiIcon.uFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP; m_NotiIcon.uCallbackMessage=WM_MY_TRAY_NOTIFICATION; //用户定义的回调消息 CString szToolTip; szToolTip=_T("W620 数据存储"); _tcscpy(m_NotiIcon.szTip, szToolTip); m_NotiIcon.uID=IDI_ICON2/*IDR_MAINFRAME*/; HICON hIcon; hIcon=AfxGetApp()->LoadIcon(IDI_ICON2); m_NotiIcon.hIcon=hIcon; ::Shell_NotifyIcon(NIM_ADD,&m_NotiIcon); if(hIcon)::DestroyIcon(hIcon); }
7. 销毁图标
void CW620Dlg::OnDestroy() { // TODO: Add your message handler code here ::Shell_NotifyIcon(NIM_DELETE,&m_NotiIcon); }
8.如要隐藏任务栏程序:
void CW620Dlg::OnNcPaint() { // TODO: Add your message handler code here static int i = 2; if(i > 0) { i --; ShowWindow(SW_HIDE); } else { CDialog::OnNcPaint(); } // Do not call CDialog::OnNcPaint() for painting messages }
9.处理最小化:
重载WindowProc函数:
WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { // TODO: Add your specialized code here and/or call the base class switch(message) { case WM_SYSCOMMAND://如果是系统消息 if(wParam==SC_MINIMIZE) { //接收到最小化消息时主窗口隐藏 AfxGetApp()->m_pMainWnd->ShowWindow(SW_HIDE); return 0; } break; } return CWnd::WindowProc(message, wParam, lParam); }
10. 显示窗体
AfxGetApp()->m_pMainWnd->ShowWindow(SW_SHOW);
11. 退出程序:
SendMessage(WM_CLOSE,0,0); or PostMessage(WM_QUITE,0,0)