///////////////////////////////////////////////////////////////////////////// // SystemTray.h : header file // // Written by Chris Maunder ([email protected]) // Copyright (c) 1998. // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name is included. If // the source code in this file is used in any commercial application // then acknowledgement must be made to the author of this file // (in whatever form you wish). // // This file is provided "as is" with no expressed or implied warranty. // The author accepts no liability if it causes any damage to your // computer, causes your pet cat to fall ill, increases baldness or // makes you car start emitting strange noises when you start it up. // // Expect bugs. // // Please use and enjoy. Please let me know of any bugs/mods/improvements // that you have found/implemented and I will fix/incorporate them into this // file. #ifndef _INCLUDED_SYSTEMTRAY_H_ #define _INCLUDED_SYSTEMTRAY_H_ #include <afxtempl.h> #include <afxwin.h> #include <atlcomtime.h> ///////////////////////////////////////////////////////////////////////////// // CSystemTray window class CSystemTray : public CWnd { // Construction/destruction public: CSystemTray(); CSystemTray(CWnd* pWnd, UINT uCallbackMessage, LPCTSTR szTip, HICON icon, UINT uID); virtual ~CSystemTray(); DECLARE_DYNAMIC(CSystemTray) // Operations public: BOOL Enabled() { return m_bEnabled; } BOOL Visible() { return !m_bHidden; } // Create the tray icon BOOL Create(CWnd* pParent, UINT uCallbackMessage, LPCTSTR szTip, HICON icon, UINT uID); // Change or retrieve the Tooltip text BOOL SetTooltipText(LPCTSTR pszTooltipText); BOOL SetTooltipText(UINT nID); CString GetTooltipText() const; // Change or retrieve the icon displayed BOOL SetIcon(HICON hIcon); BOOL SetIcon(LPCTSTR lpszIconName); BOOL SetIcon(UINT nIDResource); BOOL SetStandardIcon(LPCTSTR lpIconName); BOOL SetStandardIcon(UINT nIDResource); HICON GetIcon() const; void HideIcon(); void ShowIcon(); void RemoveIcon(); void MoveToRight(); // For icon animation BOOL SetIconList(UINT uFirstIconID, UINT uLastIconID); BOOL SetIconList(HICON* pHIconList, UINT nNumIcons); BOOL Animate(UINT nDelayMilliSeconds, int nNumSeconds = -1); BOOL StepAnimation(); BOOL StopAnimation(); // Change menu default item void GetMenuDefaultItem(UINT& uItem, BOOL& bByPos); BOOL SetMenuDefaultItem(UINT uItem, BOOL bByPos); // Change or retrieve the window to send notification messages to BOOL SetNotificationWnd(CWnd* pNotifyWnd); CWnd* GetNotificationWnd() const; // Default handler for tray notification message virtual LRESULT OnTrayNotification(WPARAM uID, LPARAM lEvent); // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CSystemTray) protected: virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); //}}AFX_VIRTUAL // Implementation protected: void Initialise(); BOOL m_bEnabled; // does O/S support tray icon? BOOL m_bHidden; // Has the icon been hidden? NOTIFYICONDATA m_tnd; CArray<HICON, HICON> m_IconList; static UINT m_nIDEvent; UINT m_uIDTimer; int m_nCurrentIcon; COleDateTime m_StartTime; int m_nAnimationPeriod; HICON m_hSavedIcon; UINT m_DefaultMenuItemID; BOOL m_DefaultMenuItemByPos; // Generated message map functions protected: //{{AFX_MSG(CSystemTray) afx_msg void OnTimer(UINT nIDEvent); //}}AFX_MSG DECLARE_MESSAGE_MAP() }; #endif
///////////////////////////////////////////////////////////////////////////// // SystemTray.cpp : implementation file // // This is a conglomeration of ideas from the MSJ "Webster" application, // sniffing round the online docs, and from other implementations such // as PJ Naughter's "CTrayNotifyIcon" (http://indigo.ie/~pjn/ntray.html) // especially the "CSystemTray::OnTrayNotification" member function. // Joerg Koenig suggested the icon animation stuff // // This class is a light wrapper around the windows system tray stuff. It // adds an icon to the system tray with the specified ToolTip text and // callback notification value, which is sent back to the Parent window. // // The tray icon can be instantiated using either the constructor or by // declaring the object and creating (and displaying) it later on in the // program. eg. // // CSystemTray m_SystemTray; // Member variable of some class // // ... // // in some member function maybe... // m_SystemTray.Create(pParentWnd, WM_MY_NOTIFY, "Click here", // hIcon, nSystemTrayID); // // Written by Chris Maunder ([email protected]) // Copyright (c) 1998. // // Updated: 25 Jul 1998 - Added icon animation, and derived class // from CWnd in order to handle messages. (CJM) // (icon animation suggested by Joerg Koenig. // Added API to set default menu item. Code provided // by Enrico Lelina. // // This code may be used in compiled form in any way you desire. This // file may be redistributed unmodified by any means PROVIDING it is // not sold for profit without the authors written consent, and // providing that this notice and the authors name is included. If // the source code in this file is used in any commercial application // then acknowledgement must be made to the author of this file // (in whatever form you wish). // // This file is provided "as is" with no expressed or implied warranty. // The author accepts no liability if it causes any damage to your // computer, causes your pet cat to fall ill, increases baldness or // makes you car start emitting strange noises when you start it up. // // Expect bugs. // // Please use and enjoy. Please let me know of any bugs/mods/improvements // that you have found/implemented and I will fix/incorporate them into this // file. // ///////////////////////////////////////////////////////////////////////////// #include "SystemTray.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif IMPLEMENT_DYNAMIC(CSystemTray, CWnd) UINT CSystemTray::m_nIDEvent = 4567; ///////////////////////////////////////////////////////////////////////////// // CSystemTray construction/creation/destruction CSystemTray::CSystemTray() { Initialise(); } CSystemTray::CSystemTray(CWnd* pParent, UINT uCallbackMessage, LPCTSTR szToolTip, HICON icon, UINT uID) { Initialise(); Create(pParent, uCallbackMessage, szToolTip, icon, uID); } void CSystemTray::Initialise() { memset(&m_tnd, 0, sizeof(m_tnd)); m_bEnabled = FALSE; m_bHidden = FALSE; m_uIDTimer = 0; m_hSavedIcon = NULL; m_DefaultMenuItemID = 0; m_DefaultMenuItemByPos = TRUE; } BOOL CSystemTray::Create(CWnd* pParent, UINT uCallbackMessage, LPCTSTR szToolTip, HICON icon, UINT uID) { // this is only for Windows 95 (or higher) VERIFY(m_bEnabled = ( GetVersion() & 0xff ) >= 4); if (!m_bEnabled) return FALSE; // Make sure Notification window is valid (not needed - CJM) // VERIFY(m_bEnabled = (pParent && ::IsWindow(pParent->GetSafeHwnd()))); // if (!m_bEnabled) return FALSE; // Make sure we avoid conflict with other messages ASSERT(uCallbackMessage >= WM_USER); // Tray only supports tooltip text up to 64 characters ASSERT(_tcslen(szToolTip) <= 64); // Create an invisible window CWnd::CreateEx(0, AfxRegisterWndClass(0), _T(""), WS_POPUP, 0,0,10,10, NULL, 0); // load up the NOTIFYICONDATA structure m_tnd.cbSize = sizeof(NOTIFYICONDATA); m_tnd.hWnd = pParent->GetSafeHwnd()? pParent->GetSafeHwnd() : m_hWnd; m_tnd.uID = uID; m_tnd.hIcon = icon; m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; m_tnd.uCallbackMessage = uCallbackMessage; _tcscpy(m_tnd.szTip, szToolTip); // Set the tray icon VERIFY(m_bEnabled = Shell_NotifyIcon(NIM_ADD, &m_tnd)); return m_bEnabled; } CSystemTray::~CSystemTray() { RemoveIcon(); m_IconList.RemoveAll(); DestroyWindow(); } ///////////////////////////////////////////////////////////////////////////// // CSystemTray icon manipulation void CSystemTray::MoveToRight() { HideIcon(); ShowIcon(); } void CSystemTray::RemoveIcon() { if (!m_bEnabled) return; m_tnd.uFlags = 0; Shell_NotifyIcon(NIM_DELETE, &m_tnd); m_bEnabled = FALSE; } void CSystemTray::HideIcon() { if (m_bEnabled && !m_bHidden) { m_tnd.uFlags = NIF_ICON; Shell_NotifyIcon (NIM_DELETE, &m_tnd); m_bHidden = TRUE; } } void CSystemTray::ShowIcon() { if (m_bEnabled && m_bHidden) { m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; Shell_NotifyIcon(NIM_ADD, &m_tnd); m_bHidden = FALSE; } } BOOL CSystemTray::SetIcon(HICON hIcon) { if (!m_bEnabled) return FALSE; m_tnd.uFlags = NIF_ICON; m_tnd.hIcon = hIcon; return Shell_NotifyIcon(NIM_MODIFY, &m_tnd); } BOOL CSystemTray::SetIcon(LPCTSTR lpszIconName) { HICON hIcon = AfxGetApp()->LoadIcon(lpszIconName); return SetIcon(hIcon); } BOOL CSystemTray::SetIcon(UINT nIDResource) { HICON hIcon = AfxGetApp()->LoadIcon(nIDResource); return SetIcon(hIcon); } BOOL CSystemTray::SetStandardIcon(LPCTSTR lpIconName) { HICON hIcon = LoadIcon(NULL, lpIconName); return SetIcon(hIcon); } BOOL CSystemTray::SetStandardIcon(UINT nIDResource) { HICON hIcon = LoadIcon(NULL, MAKEINTRESOURCE(nIDResource)); return SetIcon(hIcon); } HICON CSystemTray::GetIcon() const { return (m_bEnabled)? m_tnd.hIcon : NULL; } BOOL CSystemTray::SetIconList(UINT uFirstIconID, UINT uLastIconID) { if (uFirstIconID > uLastIconID) return FALSE; UINT uIconArraySize = uLastIconID - uFirstIconID + 1; const CWinApp * pApp = AfxGetApp(); ASSERT(pApp != 0); m_IconList.RemoveAll(); try { for (UINT i = uFirstIconID; i <= uLastIconID; i++) m_IconList.Add(pApp->LoadIcon(i)); } catch (CMemoryException *e) { e->ReportError(); e->Delete(); m_IconList.RemoveAll(); return FALSE; } return TRUE; } BOOL CSystemTray::SetIconList(HICON* pHIconList, UINT nNumIcons) { m_IconList.RemoveAll(); try { for (UINT i = 0; i <= nNumIcons; i++) m_IconList.Add(pHIconList[i]); } catch (CMemoryException *e) { e->ReportError(); e->Delete(); m_IconList.RemoveAll(); return FALSE; } return TRUE; } BOOL CSystemTray::Animate(UINT nDelayMilliSeconds, int nNumSeconds /*=-1*/) { StopAnimation(); m_nCurrentIcon = 0; m_StartTime = COleDateTime::GetCurrentTime(); m_nAnimationPeriod = nNumSeconds; m_hSavedIcon = GetIcon(); // Setup a timer for the animation m_uIDTimer = SetTimer(m_nIDEvent, nDelayMilliSeconds, NULL); return (m_uIDTimer != 0); } //show next icon BOOL CSystemTray::StepAnimation() { if (!m_IconList.GetSize()) return FALSE; m_nCurrentIcon++; if (m_nCurrentIcon >= m_IconList.GetSize()) m_nCurrentIcon = 0; return SetIcon(m_IconList[m_nCurrentIcon]); } BOOL CSystemTray::StopAnimation() { BOOL bResult = FALSE; if (m_uIDTimer) bResult = KillTimer(m_uIDTimer); m_uIDTimer = 0; if (m_hSavedIcon) SetIcon(m_hSavedIcon); m_hSavedIcon = NULL; return bResult; } ///////////////////////////////////////////////////////////////////////////// // CSystemTray tooltip text manipulation BOOL CSystemTray::SetTooltipText(LPCTSTR pszTip) { if (!m_bEnabled) return FALSE; m_tnd.uFlags = NIF_TIP; _tcscpy(m_tnd.szTip, pszTip); return Shell_NotifyIcon(NIM_MODIFY, &m_tnd); } BOOL CSystemTray::SetTooltipText(UINT nID) { CString strText; VERIFY(strText.LoadString(nID)); return SetTooltipText(strText); } CString CSystemTray::GetTooltipText() const { CString strText; if (m_bEnabled) strText = m_tnd.szTip; return strText; } ///////////////////////////////////////////////////////////////////////////// // CSystemTray notification window stuff BOOL CSystemTray::SetNotificationWnd(CWnd* pWnd) { if (!m_bEnabled) return FALSE; // Make sure Notification window is valid ASSERT(pWnd && ::IsWindow(pWnd->GetSafeHwnd())); m_tnd.hWnd = pWnd->GetSafeHwnd(); m_tnd.uFlags = 0; return Shell_NotifyIcon(NIM_MODIFY, &m_tnd); } CWnd* CSystemTray::GetNotificationWnd() const { return CWnd::FromHandle(m_tnd.hWnd); } ///////////////////////////////////////////////////////////////////////////// // CSystemTray menu manipulation BOOL CSystemTray::SetMenuDefaultItem(UINT uItem, BOOL bByPos) { if ((m_DefaultMenuItemID == uItem) && (m_DefaultMenuItemByPos == bByPos)) return TRUE; m_DefaultMenuItemID = uItem; m_DefaultMenuItemByPos = bByPos; CMenu menu, *pSubMenu; if (!menu.LoadMenu(m_tnd.uID)) return FALSE; if (!(pSubMenu = menu.GetSubMenu(0))) return FALSE; ::SetMenuDefaultItem(pSubMenu->m_hMenu, m_DefaultMenuItemID, m_DefaultMenuItemByPos); return TRUE; } void CSystemTray::GetMenuDefaultItem(UINT& uItem, BOOL& bByPos) { uItem = m_DefaultMenuItemID; bByPos = m_DefaultMenuItemByPos; } ///////////////////////////////////////////////////////////////////////////// // CSystemTray message handlers BEGIN_MESSAGE_MAP(CSystemTray, CWnd) //{{AFX_MSG_MAP(CSystemTray) ON_WM_TIMER() //}}AFX_MSG_MAP END_MESSAGE_MAP() void CSystemTray::OnTimer(UINT nIDEvent) { ASSERT(nIDEvent == m_nIDEvent); COleDateTime CurrentTime = COleDateTime::GetCurrentTime(); COleDateTimeSpan period = CurrentTime - m_StartTime; if (m_nAnimationPeriod > 0 && m_nAnimationPeriod < period.GetTotalSeconds()) { StopAnimation(); return; } StepAnimation(); } LRESULT CSystemTray::OnTrayNotification(UINT wParam, LONG lParam) { //Return quickly if its not for this tray icon if (wParam != m_tnd.uID) return 0L; CMenu menu, *pSubMenu; CWnd* pTarget = AfxGetMainWnd(); // Clicking with right button brings up a context menu if (LOWORD(lParam) == WM_RBUTTONUP) { if (!menu.LoadMenu(m_tnd.uID)) return 0; if (!(pSubMenu = menu.GetSubMenu(0))) return 0; // Make chosen menu item the default (bold font) ::SetMenuDefaultItem(pSubMenu->m_hMenu, m_DefaultMenuItemID, m_DefaultMenuItemByPos); // Display and track the popup menu CPoint pos; GetCursorPos(&pos); pTarget->SetForegroundWindow(); ::TrackPopupMenu(pSubMenu->m_hMenu, 0, pos.x, pos.y, 0, pTarget->GetSafeHwnd(), NULL); // BUGFIX: See "PRB: Menus for Notification Icons Don't Work Correctly" pTarget->PostMessage(WM_NULL, 0, 0); menu.DestroyMenu(); } else if (LOWORD(lParam) == WM_LBUTTONDBLCLK) { // double click received, the default action is to execute default menu item pTarget->ShowWindow(SW_SHOW); pTarget->SetForegroundWindow(); UINT uItem; if (m_DefaultMenuItemByPos) { if (!menu.LoadMenu(m_tnd.uID)) return 0; if (!(pSubMenu = menu.GetSubMenu(0))) return 0; uItem = pSubMenu->GetMenuItemID(m_DefaultMenuItemID); } else uItem = m_DefaultMenuItemID; pTarget->SendMessage(WM_COMMAND, uItem, 0); menu.DestroyMenu(); } return 1; } LRESULT CSystemTray::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { if (message == m_tnd.uCallbackMessage) return OnTrayNotification(wParam, lParam); return CWnd::WindowProc(message, wParam, lParam); }
对话框头文件
CSystemTray m_trayicon;
对话框cpp文件
m_trayicon.Create(this->m_pParentWnd,WM_NOTIFY,"Test",AfxGetApp()->LoadIcon(IDR_MAINFRAME),IDR_MENU1);
函数声明: BOOL Create(CWnd* pParent, UINT uCallbackMessage, LPCTSTR szTip, HICON icon, UINT uID);
this->m_pParentWnd:注意这里传递的窗口句柄必须是主窗口的父句柄。
WM_NOTIFY :为自定义消息 关联消息映射 ON_MESSAGE(WM_NOTIFY,on_notify) LRESULT on_notify(WPARAM wpara,LPARAM lpara);
szTip :为鼠标移上托管图标的提示
AfxGetApp()->LoadIcon(IDR_MAINFRAME):显示的托管图标
IDR_MENU1:为鼠标右键点击托管图标后显示的菜单。
需要做到的是,用户点击minisizebox 主窗口隐藏 转为托管,在主窗口的cpp文件处理消息
void CRegisterDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else if(nID == SC_MINIMIZE) { m_trayicon.HideIcon(); m_trayicon.MoveToRight(); this->ShowWindow(SW_HIDE); } else { CDialogEx::OnSysCommand(nID, lParam); } }到此系统托管图标完成。