二、编程步骤
1、 启动Visual C++6.0,生成一个单文档的应用程序TrayTest,取消文档视图支持;
2、 在CMainFrame类中添加自定义消息#define WM_MY_TRAY_NOTIFICATION WM_USER+0,并在该类中为此自定义消息手动添加消息映射ON_MESSAGE(WM_MY_TRAY_NOTIFICATION, OnTrayNotification)和消息响应函数afx_msg LRESULT OnTrayNotification(WPARAM wp, LPARAM lp);
3、 设计二个图标添加到项目中,其ID标志分别为"IDI_MYICON"、"IDI_MYICON2",作为托盘显示时的图标;
4、 在CMainFrame类中添加下述变量: CTrayIcon m_trayIcon(用来操作图标的类对象)、CEdit m_wndEdit(编辑框用来显示所跟踪到的鼠标消息)、int m_iWhichIcon(决定当前托盘使用哪个图标)、BOOL m_bShutdown(是否关闭当前拖盘程序标志)、BOOL m_bShowTrayNotifications(是否显示托盘消息标志);
5、 为程序的IDR_MAINFRAME添加处理菜单项和托盘的上下文菜单IDI_TRAYICON(具体的菜单项的标题和ID标志符参见代码部分),然后使用Class Wizard为各个菜单项添加处理函数;
6、 添加代码,编译运行程序。
| ////////////////////////////////////////////////CTrayIcon类的头文件; #ifndef _TRAYICON_H #define _TRAYICON_H class CTrayIcon : public CCmdTarget { protected: DECLARE_DYNAMIC(CTrayIcon) NOTIFYICONDATA m_nid; // struct for Shell_NotifyIcon args public: CTrayIcon(UINT uID); ~CTrayIcon(); // Call this to receive tray notifications void SetNotificationWnd(CWnd* pNotifyWnd, UINT uCbMsg); BOOL SetIcon(UINT uID); // main variant you want to use BOOL SetIcon(HICON hicon, LPCSTR lpTip); BOOL SetIcon(LPCTSTR lpResName, LPCSTR lpTip) { return SetIcon(lpResName ? AfxGetApp()->LoadIcon(lpResName) : NULL, lpTip); } BOOL SetStandardIcon(LPCTSTR lpszIconName, LPCSTR lpTip) { return SetIcon(::LoadIcon(NULL, lpszIconName), lpTip); } virtual LRESULT OnTrayNotification(WPARAM uID, LPARAM lEvent); }; #endif ///////////////////////////////////////////////////CTrayIcon类的.CPP文件 #include "stdafx.h" #include "trayicon.h" #include IMPLEMENT_DYNAMIC(CTrayIcon, CCmdTarget) CTrayIcon::CTrayIcon(UINT uID) { memset(&m_nid, 0 , sizeof(m_nid)); // Initialize NOTIFYICONDATA m_nid.cbSize = sizeof(m_nid); m_nid.uID = uID; // never changes after construction AfxLoadString(uID, m_nid.szTip, sizeof(m_nid.szTip)); // Use resource string as tip if there is one } CTrayIcon::~CTrayIcon() { SetIcon(0); // remove icon from system tray } void CTrayIcon::SetNotificationWnd(CWnd* pNotifyWnd, UINT uCbMsg) { // Set notification window. It must created already. ASSERT(pNotifyWnd==NULL ::IsWindow(pNotifyWnd->GetSafeHwnd())); m_nid.hWnd = pNotifyWnd->GetSafeHwnd(); ASSERT(uCbMsg==0 uCbMsg>=WM_USER); m_nid.uCallbackMessage = uCbMsg; } BOOL CTrayIcon::SetIcon(UINT uID) { // Sets both the icon and tooltip from resource ID ,To remove the icon, call SetIcon(0) HICON hicon=NULL; if (uID) { AfxLoadString(uID, m_nid.szTip, sizeof(m_nid.szTip)); hicon = AfxGetApp()->LoadIcon(uID); } return SetIcon(hicon, NULL); } BOOL CTrayIcon::SetIcon(HICON hicon, LPCSTR lpTip) { // Common SetIcon for all overloads. UINT msg; m_nid.uFlags = 0; if (hicon) { // Set the icon msg = m_nid.hIcon ? NIM_MODIFY : NIM_ADD; m_nid.hIcon = hicon; // Add or replace icon in system tray m_nid.uFlags = NIF_ICON; } else { if (m_nid.hIcon==NULL) // remove icon from tray return TRUE; // already deleted msg = NIM_DELETE; } if (lpTip) // Use the tip, if any strncpy(m_nid.szTip, lpTip, sizeof(m_nid.szTip)); if (m_nid.szTip[0]) m_nid.uFlags = NIF_TIP; if (m_nid.uCallbackMessage && m_nid.hWnd) // Use callback if any m_nid.uFlags = NIF_MESSAGE; BOOL bRet = Shell_NotifyIcon(msg, &m_nid); // Do it if (msg==NIM_DELETE !bRet) m_nid.hIcon = NULL; // failed return bRet; } LRESULT CTrayIcon::OnTrayNotification(WPARAM wID, LPARAM lEvent) { if (wID!=m_nid.uID (lEvent!=WM_RBUTTONUP && lEvent!=WM_LBUTTONDBLCLK)) return 0; CMenu menu;//装载上下文菜单; if (!menu.LoadMenu(m_nid.uID)) return 0; CMenu* pSubMenu = menu.GetSubMenu(0); if (!pSubMenu) return 0; if (lEvent==WM_RBUTTONUP) {//设置第一个菜单项为默认菜单项目 ::SetMenuDefaultItem(pSubMenu->m_hMenu, 0, TRUE); //将当前菜单作为上下文菜单; CPoint mouse; GetCursorPos(&mouse); ::SetForegroundWindow(m_nid.hWnd); ::TrackPopupMenu(pSubMenu->m_hMenu, 0, mouse.x, mouse.y, 0,m_nid.hWnd, NULL); } else // double click: execute first menu item ::SendMessage(m_nid.hWnd, WM_COMMAND, pSubMenu->GetMenuItemID(0), 0); return 1; } |

