(1). 新建一个基于对话框的应用程序
(2). 准备一些icon,典型地,如QQ游戏的安装目录下/QQGAME/Res/MainWin/Tray的几个icon,并放入当前工程目录/TrayIcon目录下
(3). 添加一些变量
HICON m_hTrayIcon[4]; CString m_strPath; NOTIFYICONDATA m_nid;
并在构造函数中初始化ZeroMemory(m_hTrayIcon, 4 * sizeof(HICON));
(4). 自定义消息,用于右击托盘弹出快捷菜单
#define UM_SHOWTASK (WM_USER + 102)
(5). 添加成员函数ToTray(), DeleteTray()
void CFlashTray_demoDlg::ToTray() { m_nid.cbSize = sizeof(NOTIFYICONDATA); m_nid.hWnd = this->GetSafeHwnd(); m_nid.uID = IDI_ICON_QQGAME; m_nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; m_nid.uVersion = NOTIFYICON_VERSION; m_nid.dwInfoFlags = NIIF_INFO; m_nid.uCallbackMessage = UM_SHOWTASK; m_nid.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICON_QQGAME)); strcpy(m_nid.szTip, _T("QQ游戏")); Shell_NotifyIcon(NIM_ADD, &m_nid); } void CFlashTray_demoDlg::DeleteTray() { m_nid.cbSize = sizeof(NOTIFYICONDATA); m_nid.hWnd = this->GetSafeHwnd(); m_nid.uID = IDI_ICON_QQGAME; Shell_NotifyIcon(NIM_DELETE, &m_nid); for (int i = 0; i < 4; i++) { if (m_hTrayIcon[i]) CloseHandle(m_hTrayIcon[i]); } }
(6). 在OnInitDialog函数中添加如下代码
BOOL CFlashTray_demoDlg::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 CString strIconPath = ""; CString strTrayDir = "//TrayIcon//"; GetModuleFileName(NULL, m_strPath.GetBufferSetLength(MAX_PATH + 1), MAX_PATH); m_strPath.ReleaseBuffer(); int nPosition; nPosition = m_strPath.ReverseFind('//'); m_strPath = m_strPath.Left(nPosition); nPosition = m_strPath.ReverseFind('//'); m_strPath = m_strPath.Left(nPosition); strIconPath = m_strPath + strTrayDir + "loading01-256.ico"; m_hTrayIcon[0] = (HICON)::LoadImage(NULL, strIconPath, IMAGE_ICON, 0, 0, LR_LOADFROMFILE); strIconPath = m_strPath + strTrayDir + "loading02-256.ico"; m_hTrayIcon[1] = (HICON)::LoadImage(NULL, strIconPath, IMAGE_ICON, 0, 0, LR_LOADFROMFILE); strIconPath = m_strPath + strTrayDir + "loading03-256.ico"; m_hTrayIcon[2] = (HICON)::LoadImage(NULL, strIconPath, IMAGE_ICON, 0, 0, LR_LOADFROMFILE); strIconPath = m_strPath + strTrayDir + "loading04-256.ico"; m_hTrayIcon[3] = (HICON)::LoadImage(NULL, strIconPath, IMAGE_ICON, 0, 0, LR_LOADFROMFILE); if (NULL == m_hTrayIcon[0] || NULL == m_hTrayIcon[1] || NULL == m_hTrayIcon[2] || NULL == m_hTrayIcon[3]) { MessageBox(_T("加载Icon图标失败!")); PostQuitMessage(0x0001); } ToTray(); return TRUE; // return TRUE unless you set the focus to a control }
(6). 为UM_SHOWTASK添加消息响应函数afx_msg LRESULT OnShowTask(WPARAM wParam, LPARAM lParam);
LRESULT CFlashTray_demoDlg::OnShowTask(WPARAM wParam, LPARAM lParam) { if (wParam != IDI_ICON_QQGAME) { return 1; } switch (lParam) { case WM_RBUTTONUP: { LPPOINT lpoint = new tagPOINT; ::GetCursorPos(lpoint); CMenu menu; menu.CreatePopupMenu(); menu.AppendMenu(MF_STRING, IDM_MENU_EXIT, "退出"); // 确定弹出式菜单的位置 ::SetForegroundWindow(this->GetSafeHwnd()); menu.TrackPopupMenu(TPM_RIGHTALIGN, lpoint->x, lpoint->y, this); HMENU hmenu = menu.Detach(); // 资源回收 menu.DestroyMenu(); delete lpoint; } break; } return 0; }
这里的IDM_MENU_EXIT可在resource.h中定义,为其响应命令消息响应
void CFlashTray_demoDlg::OnMenuExit() { PostQuitMessage(0); }
(7). 准备一个BUTTON,为其响应单击消息响应
void CFlashTray_demoDlg::OnButton1() { // TODO: Add your control notification handler code here UpdateData(); CString strText; if (GetDlgItem(IDC_BUTTON1)->GetWindowText(strText), strText == "StartFlashing") { GetDlgItem(IDC_BUTTON1)->SetWindowText("StopFlashing"); SetTimer(1, 100, NULL);// 触发托盘图标闪动 } else { ASSERT(strText == "StopFlashing"); GetDlgItem(IDC_BUTTON1)->SetWindowText("StartFlashing"); KillTimer(1); m_nid.uID = IDI_ICON_QQGAME; m_nid.cbSize = sizeof(NOTIFYICONDATA); m_nid.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICON_QQGAME)); m_nid.hWnd = this->GetSafeHwnd(); m_nid.uFlags = NIF_ICON | NIF_TIP; strcpy(m_nid.szTip, _T("QQ游戏")); Shell_NotifyIcon(NIM_MODIFY, &m_nid); } }
(8). 为对话框响应WM_TIMER
void CFlashTray_demoDlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default m_nid.uID = IDI_ICON_QQGAME; m_nid.cbSize = (DWORD)sizeof(NOTIFYICONDATA); m_nid.hWnd = this->GetSafeHwnd(); m_nid.uFlags = NIF_ICON | NIF_TIP; strcpy(m_nid.szTip, _T("QQ游戏")); static int i = 0; switch (nIDEvent) { case 1: { m_nid.hIcon = m_hTrayIcon[i]; Shell_NotifyIcon(NIM_MODIFY, &m_nid); i = (++i) % 4; } break; } CDialog::OnTimer(nIDEvent); }
(9). 最后在OnDestroy中调用DeleteTray
void CFlashTray_demoDlg::OnDestroy() { CDialog::OnDestroy(); // TODO: Add your message handler code here DeleteTray(); }