| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133 | 
							- /////////////////////////////////////////////////////////////////////////////
 
- // SystemTray.cpp : implementation file
 
- //
 
- // MFC VERSION
 
- //
 
- // 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.
 
- //
 
- // Updated: 6 June 1999 - SetIcon can now load non-standard sized icons (Chip Calvert)
 
- //                        Added "bHidden" parameter when creating icon
 
- //                        (Thanks to Michael Gombar for these suggestions)
 
- //                        Restricted tooltip text to 64 characters.
 
- //
 
- // Updated: 9 Nov 1999  - Now works in WindowsCE.
 
- //                        Fix for use in NT services (Thomas Mooney, TeleProc, Inc)
 
- //                        Added W2K stuff by Michael Dunn
 
- //
 
- // Updated: 1 Jan 2000  - Added tray minimisation stuff.
 
- // 
 
- // Updated: 21 Sep 2000 - Added GetDoWndAnimation - animation only occurs if the system
 
- //                        settings allow it (Matthew Ellis). Updated the GetTrayWndRect
 
- //                        function to include more fallback logic (Matthew Ellis)
 
- //                        NOTE: Signature of GetTrayWndRect has changed!
 
- //
 
- // Updated: 16 Jun 2002 - Fixed stupid errors so that it compiles clean on VC7
 
- //
 
- // 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 for any damage caused through use.
 
- //
 
- // 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 "stdafx.h"
 
- #include "SystemTray.h"
 
- #ifdef _DEBUG
 
- #define new DEBUG_NEW
 
- #undef THIS_FILE
 
- static char THIS_FILE[] = __FILE__;
 
- #endif
 
- #ifndef _WIN32_WCE  // Use C++ exception handling instead of structured.
 
- #undef TRY
 
- #undef CATCH
 
- #undef END_CATCH
 
- #define TRY try
 
- #define CATCH(ex_class, ex_object) catch(ex_class* ex_object)
 
- #define END_CATCH
 
- #endif  // _WIN32_WCE
 
- #ifndef _countof
 
- #define _countof(x) ( sizeof(x) / sizeof(x[0]) )
 
- #endif
 
- IMPLEMENT_DYNAMIC(CSystemTray, CWnd)
 
- const UINT CSystemTray::m_nTimerID    = 4567;
 
- UINT CSystemTray::m_nMaxTooltipLength  = 64;     // This may change...
 
- const UINT CSystemTray::m_nTaskbarCreatedMsg = ::RegisterWindowMessage(_T("TaskbarCreated"));
 
- CTrayWnd  CSystemTray::m_wndInvisible;
 
- BOOL CSystemTray::m_bShowWndAnimation;
 
- /////////////////////////////////////////////////////////////////////////////
 
- // CSystemTray construction/creation/destruction
 
- CSystemTray::CSystemTray()
 
- {
 
-     Initialise();
 
- }
 
- CSystemTray::CSystemTray(CWnd* pParent,             // The window that will recieve tray notifications
 
-                          UINT uCallbackMessage,     // the callback message to send to parent
 
-                          LPCTSTR szToolTip,         // tray icon tooltip
 
-                          HICON icon,                // Handle to icon
 
-                          UINT uID,                  // Identifier of tray icon
 
-                          BOOL bHidden /*=FALSE*/,   // Hidden on creation?                  
 
-                          LPCTSTR szBalloonTip /*=NULL*/,    // Ballon tip (w2k only)
 
-                          LPCTSTR szBalloonTitle /*=NULL*/,  // Balloon tip title (w2k)
 
-                          DWORD dwBalloonIcon /*=NIIF_NONE*/,// Ballon tip icon (w2k)
 
-                          UINT uBalloonTimeout /*=10*/)      // Balloon timeout (w2k)
 
- {
 
-     Initialise();
 
-     Create(pParent, uCallbackMessage, szToolTip, icon, uID, bHidden,
 
-            szBalloonTip, szBalloonTitle, dwBalloonIcon, uBalloonTimeout);
 
- }
 
- void CSystemTray::Initialise()
 
- {
 
-     memset(&m_tnd, 0, sizeof(m_tnd));
 
-     m_bEnabled = FALSE;
 
-     m_bHidden  = TRUE;
 
-     m_bRemoved = TRUE;
 
-     m_DefaultMenuItemID    = 0;
 
-     m_DefaultMenuItemByPos = TRUE;
 
-     m_bShowIconPending = FALSE;
 
-     m_uIDTimer   = 0;
 
-     m_hSavedIcon = NULL;
 
- 	m_pTargetWnd = NULL;
 
- 	m_uCreationFlags = 0;
 
- 	m_bShowWndAnimation = FALSE;
 
- 	m_bSingleClickSelect = FALSE;
 
- #ifdef SYSTEMTRAY_USEW2K
 
-     //OSVERSIONINFOW os = { sizeof(os) };
 
- 	//GetVersionExW(&os);
 
- 	m_bWin2K = true;// (VER_PLATFORM_WIN32_NT == os.dwPlatformId && os.dwMajorVersion >= 5);
 
- #else
 
-     m_bWin2K = FALSE;
 
- #endif
 
- }
 
- // update by Michael Dunn, November 1999
 
- //
 
- //  New version of Create() that handles new features in Win 2K.
 
- //
 
- // Changes:
 
- //  szTip: Same as old, but can be 128 characters instead of 64.
 
- //  szBalloonTip: Text for a balloon tooltip that is shown when the icon
 
- //                is first added to the tray.  Pass "" if you don't want
 
- //                a balloon.
 
- //  szBalloonTitle: Title text for the balloon tooltip.  This text is shown
 
- //                  in bold above the szBalloonTip text.  Pass "" if you
 
- //                  don't want a title.
 
- //  dwBalloonIcon: Specifies which icon will appear in the balloon.  Legal
 
- //                 values are:
 
- //                     NIIF_NONE: No icon
 
- //                     NIIF_INFO: Information
 
- //                     NIIF_WARNING: Exclamation
 
- //                     NIIF_ERROR: Critical error (red circle with X)
 
- //  uBalloonTimeout: Number of seconds for the balloon to remain visible.
 
- //                   Must be between 10 and 30 inclusive.
 
- BOOL CSystemTray::Create(CWnd* pParent, UINT uCallbackMessage, LPCTSTR szToolTip, 
 
-                          HICON icon, UINT uID, BOOL bHidden /*=FALSE*/,
 
-                          LPCTSTR szBalloonTip /*=NULL*/, 
 
-                          LPCTSTR szBalloonTitle /*=NULL*/,  
 
-                          DWORD dwBalloonIcon /*=NIIF_NONE*/,
 
-                          UINT uBalloonTimeout /*=10*/)
 
- {
 
- #ifdef _WIN32_WCE
 
-     m_bEnabled = TRUE;
 
- #else
 
-     // this is only for Windows 95 (or higher)
 
- 	m_bEnabled = true;// (GetVersion() & 0xff) >= 4;
 
-     if (!m_bEnabled) 
 
-     {
 
-         ASSERT(FALSE);
 
-         return FALSE;
 
-     }
 
- #endif
 
-     m_nMaxTooltipLength = _countof(m_tnd.szTip);
 
-     
 
-     // Make sure we avoid conflict with other messages
 
-     ASSERT(uCallbackMessage >= WM_APP);
 
-     // Tray only supports tooltip text up to m_nMaxTooltipLength) characters
 
-     ASSERT(AfxIsValidString(szToolTip));
 
-     ASSERT(_tcslen(szToolTip) <= m_nMaxTooltipLength);
 
-     // Create an invisible window
 
-     CWnd::CreateEx(0, AfxRegisterWndClass(0), _T(""), WS_POPUP, 0,0,0,0, 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;
 
-     _tcsncpy(m_tnd.szTip, szToolTip, m_nMaxTooltipLength-1);
 
- #ifdef SYSTEMTRAY_USEW2K
 
-     if (m_bWin2K && szBalloonTip)
 
-     {
 
-         // The balloon tooltip text can be up to 255 chars long.
 
-         ASSERT(AfxIsValidString(szBalloonTip));
 
-         ASSERT(lstrlen(szBalloonTip) < 256);
 
-         // The balloon title text can be up to 63 chars long.
 
-         if (szBalloonTitle)
 
-         {
 
-             ASSERT(AfxIsValidString(szBalloonTitle));
 
-             ASSERT(lstrlen(szBalloonTitle) < 64);
 
-         }
 
-         // dwBalloonIcon must be valid.
 
-         ASSERT(NIIF_NONE == dwBalloonIcon    || NIIF_INFO == dwBalloonIcon ||
 
-                NIIF_WARNING == dwBalloonIcon || NIIF_ERROR == dwBalloonIcon);
 
-         // The timeout must be between 10 and 30 seconds.
 
-         ASSERT(uBalloonTimeout >= 10 && uBalloonTimeout <= 30);
 
-         m_tnd.uFlags |= NIF_INFO;
 
-         _tcsncpy(m_tnd.szInfo, szBalloonTip, 255);
 
-         if (szBalloonTitle)
 
-             _tcsncpy(m_tnd.szInfoTitle, szBalloonTitle, 63);
 
-         else
 
-             m_tnd.szInfoTitle[0] = _T('\0');
 
-         m_tnd.uTimeout    = uBalloonTimeout * 1000; // convert time to ms
 
-         m_tnd.dwInfoFlags = dwBalloonIcon;
 
-     }
 
- #endif
 
-     m_bHidden = bHidden;
 
- #ifdef SYSTEMTRAY_USEW2K    
 
-     if (m_bWin2K && m_bHidden)
 
-     {
 
-         m_tnd.uFlags = NIF_STATE;
 
-         m_tnd.dwState = NIS_HIDDEN;
 
-         m_tnd.dwStateMask = NIS_HIDDEN;
 
-     }
 
- #endif
 
- 	m_uCreationFlags = m_tnd.uFlags;	// Store in case we need to recreate in OnTaskBarCreate
 
-     BOOL bResult = TRUE;
 
-     if (!m_bHidden || m_bWin2K)
 
-     {
 
-         bResult = Shell_NotifyIcon(NIM_ADD, &m_tnd);
 
-         m_bShowIconPending = m_bHidden = m_bRemoved = !bResult;
 
-     }
 
-     
 
- #ifdef SYSTEMTRAY_USEW2K    
 
-     if (m_bWin2K && szBalloonTip)
 
-     {
 
-         // Zero out the balloon text string so that later operations won't redisplay
 
-         // the balloon.
 
-         m_tnd.szInfo[0] = _T('\0');
 
-     }
 
- #endif
 
-     return bResult;
 
- }
 
- CSystemTray::~CSystemTray()
 
- {
 
-     RemoveIcon();
 
-     m_IconList.RemoveAll();
 
-     DestroyWindow();
 
- }
 
- /////////////////////////////////////////////////////////////////////////////
 
- // CSystemTray icon manipulation
 
- //////////////////////////////////////////////////////////////////////////
 
- //
 
- // Function:    SetFocus()
 
- //
 
- // Description:
 
- //  Sets the focus to the tray icon.  Microsoft's Win 2K UI guidelines
 
- //  say you should do this after the user dismisses the icon's context
 
- //  menu.
 
- //
 
- // Input:
 
- //  Nothing.
 
- //
 
- // Returns:
 
- //  Nothing.
 
- //
 
- //////////////////////////////////////////////////////////////////////////
 
- // Added by Michael Dunn, November, 1999
 
- //////////////////////////////////////////////////////////////////////////
 
- void CSystemTray::SetFocus()
 
- {
 
- #ifdef SYSTEMTRAY_USEW2K
 
-     Shell_NotifyIcon ( NIM_SETFOCUS, &m_tnd );
 
- #endif
 
- }
 
- BOOL CSystemTray::MoveToRight()
 
- {
 
-     RemoveIcon();
 
-     return AddIcon();
 
- }
 
- BOOL CSystemTray::AddIcon()
 
- {
 
-     if (!m_bRemoved)
 
-         RemoveIcon();
 
-     if (m_bEnabled)
 
-     {
 
-         m_tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
 
-         if (!Shell_NotifyIcon(NIM_ADD, &m_tnd))
 
-             m_bShowIconPending = TRUE;
 
-         else
 
-             m_bRemoved = m_bHidden = FALSE;
 
-     }
 
-     return (m_bRemoved == FALSE);
 
- }
 
- BOOL CSystemTray::RemoveIcon()
 
- {
 
-     m_bShowIconPending = FALSE;
 
-     if (!m_bEnabled || m_bRemoved)
 
-         return TRUE;
 
-     m_tnd.uFlags = 0;
 
-     if (Shell_NotifyIcon(NIM_DELETE, &m_tnd))
 
-         m_bRemoved = m_bHidden = TRUE;
 
-     return (m_bRemoved == TRUE);
 
- }
 
- BOOL CSystemTray::HideIcon()
 
- {
 
-     if (!m_bEnabled || m_bRemoved || m_bHidden)
 
-         return TRUE;
 
- #ifdef SYSTEMTRAY_USEW2K
 
-     if (m_bWin2K)
 
-     {
 
-         m_tnd.uFlags = NIF_STATE;
 
-         m_tnd.dwState = NIS_HIDDEN;
 
-         m_tnd.dwStateMask = NIS_HIDDEN;
 
-         m_bHidden = Shell_NotifyIcon( NIM_MODIFY, &m_tnd);
 
-     }
 
-     else
 
- #endif
 
-         RemoveIcon();
 
-     return (m_bHidden == TRUE);
 
- }
 
- BOOL CSystemTray::ShowIcon()
 
- {
 
-     if (m_bRemoved)
 
-         return AddIcon();
 
-     if (!m_bHidden)
 
-         return TRUE;
 
- #ifdef SYSTEMTRAY_USEW2K
 
-     if (m_bWin2K)
 
-     {
 
-         m_tnd.uFlags = NIF_STATE;
 
-         m_tnd.dwState = 0;
 
-         m_tnd.dwStateMask = NIS_HIDDEN;
 
-         m_bHidden = !Shell_NotifyIcon ( NIM_MODIFY, &m_tnd );
 
-     }
 
-     else
 
- #endif
 
-         AddIcon();
 
-     return (m_bHidden == FALSE);
 
- }
 
- BOOL CSystemTray::SetIcon(HICON hIcon)
 
- {
 
-     if (!m_bEnabled)
 
-         return FALSE;
 
-     m_tnd.uFlags = NIF_ICON;
 
-     m_tnd.hIcon = hIcon;
 
-     if (m_bHidden)
 
-         return TRUE;
 
-     else
 
-         return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
 
- }
 
- BOOL CSystemTray::SetIcon(LPCTSTR lpszIconName)
 
- {
 
-     HICON hIcon = (HICON) ::LoadImage(AfxGetResourceHandle(), 
 
-                                       lpszIconName,
 
-                                       IMAGE_ICON, 
 
-                                       0, 0,
 
-                                       LR_DEFAULTCOLOR | LR_SHARED);
 
-     return SetIcon(hIcon);
 
- }
 
- BOOL CSystemTray::SetIcon(UINT nIDResource)
 
- {
 
-     return SetIcon(MAKEINTRESOURCE(nIDResource));
 
- }
 
- BOOL CSystemTray::SetStandardIcon(LPCTSTR lpIconName)
 
- {
 
-     HICON hIcon = LoadIcon(NULL, lpIconName);
 
-     return SetIcon(hIcon);
 
- }
 
- BOOL CSystemTray::SetStandardIcon(UINT nIDResource)
 
- {
 
- 	return SetStandardIcon(MAKEINTRESOURCE(nIDResource));
 
- }
 
-  
 
- HICON CSystemTray::GetIcon() const
 
- {
 
-     return (m_bEnabled)? m_tnd.hIcon : NULL;
 
- }
 
- BOOL CSystemTray::SetIconList(UINT uFirstIconID, UINT uLastIconID) 
 
- {
 
- 	if (uFirstIconID > uLastIconID)
 
-         return FALSE;
 
- 	const CWinApp* pApp = AfxGetApp();
 
-     if (!pApp)
 
-     {
 
-         ASSERT(FALSE);
 
-         return FALSE;
 
-     }
 
-     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;
 
-     }
 
-     END_CATCH
 
-     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;
 
-     }
 
-     END_CATCH
 
-     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 = (UINT)SetTimer(m_nTimerID, nDelayMilliSeconds, NULL);
 
-     return (m_uIDTimer != 0);
 
- }
 
- 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)
 
- {
 
-     ASSERT(AfxIsValidString(pszTip)); // (md)
 
-     ASSERT(_tcslen(pszTip) < m_nMaxTooltipLength);
 
-     if (!m_bEnabled) 
 
-         return FALSE;
 
-     m_tnd.uFlags = NIF_TIP;
 
-     _tcsncpy(m_tnd.szTip, pszTip, m_nMaxTooltipLength-1);
 
-     if (m_bHidden)
 
-         return TRUE;
 
-     else
 
-         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 support for Win 2K features.
 
- //////////////////////////////////////////////////////////////////////////
 
- //
 
- // Function:    ShowBalloon
 
- //
 
- // Description:
 
- //  Shows a balloon tooltip over the tray icon.
 
- //
 
- // Input:
 
- //  szText: [in] Text for the balloon tooltip.
 
- //  szTitle: [in] Title for the balloon.  This text is shown in bold above
 
- //           the tooltip text (szText).  Pass "" if you don't want a title.
 
- //  dwIcon: [in] Specifies an icon to appear in the balloon.  Legal values are:
 
- //                 NIIF_NONE: No icon
 
- //                 NIIF_INFO: Information
 
- //                 NIIF_WARNING: Exclamation
 
- //                 NIIF_ERROR: Critical error (red circle with X)
 
- //  uTimeout: [in] Number of seconds for the balloon to remain visible.  Can
 
- //            be between 10 and 30 inclusive.
 
- //
 
- // Returns:
 
- //  TRUE if successful, FALSE if not.
 
- //
 
- //////////////////////////////////////////////////////////////////////////
 
- // Added by Michael Dunn, November 1999
 
- //////////////////////////////////////////////////////////////////////////
 
- BOOL CSystemTray::ShowBalloon(LPCTSTR szText,
 
-                               LPCTSTR szTitle  /*=NULL*/,
 
-                               DWORD   dwIcon   /*=NIIF_NONE*/,
 
-                               UINT    uTimeout /*=10*/ )
 
- {
 
- #ifndef SYSTEMTRAY_USEW2K
 
-     return FALSE;
 
- #else
 
-     // Bail out if we're not on Win 2K.
 
-     if (!m_bWin2K)
 
-         return FALSE;
 
-     // Verify input parameters.
 
-     // The balloon tooltip text can be up to 255 chars long.
 
-     ASSERT(AfxIsValidString(szText));
 
-     ASSERT(lstrlen(szText) < 256);
 
-     // The balloon title text can be up to 63 chars long.
 
-     if (szTitle)
 
-     {
 
-         ASSERT(AfxIsValidString( szTitle));
 
-         ASSERT(lstrlen(szTitle) < 64);
 
-     }
 
-     // dwBalloonIcon must be valid.
 
-     ASSERT(NIIF_NONE == dwIcon    || NIIF_INFO == dwIcon ||
 
-            NIIF_WARNING == dwIcon || NIIF_ERROR == dwIcon);
 
-     // The timeout must be between 10 and 30 seconds.
 
-     ASSERT(uTimeout >= 0 && uTimeout <= 30);
 
-     m_tnd.uFlags = NIF_INFO;
 
-     _tcsncpy(m_tnd.szInfo, szText, 256);
 
-     if (szTitle)
 
-         _tcsncpy(m_tnd.szInfoTitle, szTitle, 64);
 
-     else
 
-         m_tnd.szInfoTitle[0] = _T('\0');
 
-     m_tnd.dwInfoFlags = dwIcon;
 
-     m_tnd.uTimeout = uTimeout * 1000;   // convert time to ms
 
-     BOOL bSuccess = Shell_NotifyIcon (NIM_MODIFY, &m_tnd);
 
-     // Zero out the balloon text string so that later operations won't redisplay
 
-     // the balloon.
 
-     m_tnd.szInfo[0] = _T('\0');
 
-     return bSuccess;
 
- #endif
 
- }
 
- /////////////////////////////////////////////////////////////////////////////
 
- // CSystemTray notification window stuff
 
- BOOL CSystemTray::SetNotificationWnd(CWnd* pWnd)
 
- {
 
-     if (!m_bEnabled) 
 
-         return FALSE;
 
-     // Make sure Notification window is valid
 
-     if (!pWnd || !::IsWindow(pWnd->GetSafeHwnd()))
 
-     {
 
-         ASSERT(FALSE);
 
-         return FALSE;
 
-     }
 
-     m_tnd.hWnd = pWnd->GetSafeHwnd();
 
-     m_tnd.uFlags = 0;
 
-     if (m_bHidden)
 
-         return TRUE;
 
-     else
 
-         return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
 
- }
 
- CWnd* CSystemTray::GetNotificationWnd() const
 
- {
 
-     return CWnd::FromHandle(m_tnd.hWnd);
 
- }
 
- // Hatr added
 
- // Hatr added
 
- // Change or retrive the window to send menu commands to
 
- BOOL CSystemTray::SetTargetWnd(CWnd* pTargetWnd)
 
- {
 
-     m_pTargetWnd = pTargetWnd;
 
-     return TRUE;
 
- } // CSystemTray::SetTargetWnd()
 
- CWnd* CSystemTray::GetTargetWnd() const
 
- {
 
-     if (m_pTargetWnd)
 
-         return m_pTargetWnd;
 
-     else
 
-         return AfxGetMainWnd();
 
- } // CSystemTray::GetTargetWnd()
 
- /////////////////////////////////////////////////////////////////////////////
 
- // CSystemTray notification message stuff
 
- BOOL CSystemTray::SetCallbackMessage(UINT uCallbackMessage)
 
- {
 
-     if (!m_bEnabled)
 
-         return FALSE;
 
-     // Make sure we avoid conflict with other messages
 
-     ASSERT(uCallbackMessage >= WM_APP);
 
-     m_tnd.uCallbackMessage = uCallbackMessage;
 
-     m_tnd.uFlags = NIF_MESSAGE;
 
-     if (m_bHidden)
 
-         return TRUE;
 
-     else
 
-         return Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
 
- }
 
- UINT CSystemTray::GetCallbackMessage() const
 
- {
 
-     return m_tnd.uCallbackMessage;
 
- }
 
- /////////////////////////////////////////////////////////////////////////////
 
- // CSystemTray menu manipulation
 
- BOOL CSystemTray::SetMenuDefaultItem(UINT uItem, BOOL bByPos)
 
- {
 
- #ifdef _WIN32_WCE
 
-     return FALSE;
 
- #else
 
-     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;
 
-     pSubMenu = menu.GetSubMenu(0);
 
-     if (!pSubMenu)
 
-         return FALSE;
 
-     ::SetMenuDefaultItem(pSubMenu->m_hMenu, m_DefaultMenuItemID, m_DefaultMenuItemByPos);
 
-     return TRUE;
 
- #endif
 
- }
 
- 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
 
- #ifndef _WIN32_WCE
 
- 	ON_WM_SETTINGCHANGE()
 
- #endif
 
-     ON_REGISTERED_MESSAGE(CSystemTray::m_nTaskbarCreatedMsg, OnTaskbarCreated)
 
- END_MESSAGE_MAP()
 
- void CSystemTray::OnTimer(UINT_PTR nIDEvent) 
 
- {
 
-     if (nIDEvent != m_uIDTimer)
 
-     {
 
-         ASSERT(FALSE);
 
-         return;
 
-     }
 
-     COleDateTime CurrentTime = COleDateTime::GetCurrentTime();
 
-     COleDateTimeSpan period = CurrentTime - m_StartTime;
 
-     if (m_nAnimationPeriod > 0 && m_nAnimationPeriod < period.GetTotalSeconds())
 
-     {
 
-         StopAnimation();
 
-         return;
 
-     }
 
-     StepAnimation();
 
- }
 
- // This is called whenever the taskbar is created (eg after explorer crashes
 
- // and restarts. Please note that the WM_TASKBARCREATED message is only passed
 
- // to TOP LEVEL windows (like WM_QUERYNEWPALETTE)
 
- LRESULT CSystemTray::OnTaskbarCreated(WPARAM /*wParam*/, LPARAM /*lParam*/) 
 
- {
 
-     InstallIconPending();
 
- 	return 0L;
 
- }
 
- #ifndef _WIN32_WCE
 
- void CSystemTray::OnSettingChange(UINT uFlags, LPCTSTR lpszSection) 
 
- {
 
- 	CWnd::OnSettingChange(uFlags, lpszSection);
 
-     if (uFlags == SPI_SETWORKAREA)
 
-         InstallIconPending();	
 
- }
 
- #endif
 
- LRESULT CSystemTray::OnTrayNotification(WPARAM wParam, LPARAM lParam) 
 
- {
 
-     //Return quickly if its not for this tray icon
 
-     if (wParam != m_tnd.uID)
 
-         return 0L;
 
-     CMenu menu, *pSubMenu;
 
-     CWnd *pTargetWnd = GetTargetWnd();
 
-     if (!pTargetWnd)
 
-         return 0L;
 
- 	// target before mouse messages change the focus
 
- 	if(WM_MOUSEFIRST <= LOWORD(lParam) && LOWORD(lParam) <= WM_MOUSELAST)
 
- 	{
 
- 		pTargetWnd->SendMessage(WM_TRAY_MENU_MOUSE_MOVE, 0, 0);
 
- 	}
 
-     // Clicking with right button brings up a context menu
 
- #if defined(_WIN32_WCE) //&& _WIN32_WCE < 211
 
-     BOOL bAltPressed = ((GetKeyState(VK_MENU) & (1 << (sizeof(SHORT)*8-1))) != 0);
 
-     if (LOWORD(lParam) == WM_LBUTTONUP && bAltPressed)
 
- #else
 
-     if (LOWORD(lParam) == WM_RBUTTONUP)
 
- #endif
 
-     {    
 
-         if (!menu.LoadMenu(m_tnd.uID))
 
-             return 0;
 
-         
 
-         pSubMenu = menu.GetSubMenu(0);
 
-         if (!pSubMenu)
 
-             return 0;
 
- #ifndef _WIN32_WCE
 
-         // Make chosen menu item the default (bold font)
 
-         ::SetMenuDefaultItem(pSubMenu->m_hMenu, m_DefaultMenuItemID, m_DefaultMenuItemByPos);
 
- #endif
 
-         // Display and track the popup menu
 
-         CPoint pos;
 
- #ifdef _WIN32_WCE
 
-         pos = CPoint(GetMessagePos());
 
- #else
 
-         GetCursorPos(&pos);
 
- #endif
 
-         pTargetWnd->SetForegroundWindow(); 
 
-         
 
- #ifndef _WIN32_WCE
 
- 		pTargetWnd->SendMessage(WM_CUSTOMIZE_TRAY_MENU, (WPARAM)pSubMenu, 0);
 
-         ::TrackPopupMenu(pSubMenu->m_hMenu, 0, pos.x, pos.y, 0, 
 
-                          pTargetWnd->GetSafeHwnd(), NULL);
 
- #else
 
-         pSubMenu->TrackPopupMenu(TPM_LEFTALIGN, pos.x, pos.y, pTargetWnd, NULL);
 
- #endif
 
-         // BUGFIX: See "PRB: Menus for Notification Icons Don't Work Correctly"
 
-         pTargetWnd->PostMessage(WM_NULL, 0, 0);
 
-         menu.DestroyMenu();
 
-     } 
 
- #if defined(_WIN32_WCE) //&& _WIN32_WCE < 211
 
-     if (LOWORD(lParam) == WM_LBUTTONDBLCLK && bAltPressed)
 
- #else
 
-     else if((LOWORD(lParam) == WM_LBUTTONDBLCLK) ||  (LOWORD(lParam) == WM_LBUTTONUP && m_bSingleClickSelect))
 
- #endif
 
-     {
 
-         // double click received, the default action is to execute default menu item
 
-         pTargetWnd->SetForegroundWindow();  
 
-         UINT uItem;
 
-         if (m_DefaultMenuItemByPos)
 
-         {
 
-             if (!menu.LoadMenu(m_tnd.uID))
 
-                 return 0;
 
-             
 
-             pSubMenu = menu.GetSubMenu(0);
 
-             if (!pSubMenu)
 
-                 return 0;
 
-             
 
-             uItem = pSubMenu->GetMenuItemID(m_DefaultMenuItemID);
 
- 			menu.DestroyMenu();
 
-         }
 
-         else
 
-             uItem = m_DefaultMenuItemID;
 
-         
 
-         pTargetWnd->SendMessage(WM_COMMAND, uItem, 0);
 
-     }
 
-     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);
 
- }
 
- void CSystemTray::InstallIconPending()
 
- {
 
-     // Is the icon display pending, and it's not been set as "hidden"?
 
-     if (!m_bShowIconPending || m_bHidden)
 
-         return;
 
- 	// Reset the flags to what was used at creation
 
- 	m_tnd.uFlags = m_uCreationFlags;
 
-     // Try and recreate the icon
 
-     m_bHidden = !Shell_NotifyIcon(NIM_ADD, &m_tnd);
 
-     // If it's STILL hidden, then have another go next time...
 
-     m_bShowIconPending = !m_bHidden;
 
-     ASSERT(m_bHidden == FALSE);
 
- }
 
- /////////////////////////////////////////////////////////////////////////////
 
- // For minimising/maximising from system tray
 
- BOOL CALLBACK FindTrayWnd(HWND hwnd, LPARAM lParam)
 
- {
 
-     TCHAR szClassName[256];
 
-     GetClassName(hwnd, szClassName, 255);
 
- 	
 
-     // Did we find the Main System Tray? If so, then get its size and keep going
 
-     if (_tcscmp(szClassName, _T("TrayNotifyWnd")) == 0)
 
-     {
 
-         CRect *pRect = (CRect*) lParam;
 
-         ::GetWindowRect(hwnd, pRect);
 
-         return TRUE;
 
-     }
 
- 	
 
-     // Did we find the System Clock? If so, then adjust the size of the rectangle
 
-     // we have and quit (clock will be found after the system tray)
 
-     if (_tcscmp(szClassName, _T("TrayClockWClass")) == 0)
 
-     {
 
-         CRect *pRect = (CRect*) lParam;
 
-         CRect rectClock;
 
-         ::GetWindowRect(hwnd, rectClock);
 
-         // if clock is above system tray adjust accordingly
 
-         if (rectClock.bottom < pRect->bottom-5) // 10 = random fudge factor.
 
-             pRect->top = rectClock.bottom;
 
-         else
 
-             pRect->right = rectClock.left;
 
-         return FALSE;
 
-     }
 
- 	
 
-     return TRUE;
 
- }
 
-  
 
- #ifndef _WIN32_WCE
 
- // enhanced version by Matthew Ellis <[email protected]>
 
- void CSystemTray::GetTrayWndRect(LPRECT lprect)
 
- {
 
- #define DEFAULT_RECT_WIDTH 150
 
- #define DEFAULT_RECT_HEIGHT 30
 
- 	
 
-     HWND hShellTrayWnd = ::FindWindow(_T("Shell_TrayWnd"), NULL);
 
-     if (hShellTrayWnd)
 
-     {
 
-         ::GetWindowRect(hShellTrayWnd, lprect);
 
-         EnumChildWindows(hShellTrayWnd, FindTrayWnd, (LPARAM)lprect);
 
-         return;
 
-     }
 
-     // OK, we failed to get the rect from the quick hack. Either explorer isn't
 
-     // running or it's a new version of the shell with the window class names
 
-     // changed (how dare Microsoft change these undocumented class names!) So, we
 
-     // try to find out what side of the screen the taskbar is connected to. We
 
-     // know that the system tray is either on the right or the bottom of the
 
-     // taskbar, so we can make a good guess at where to minimize to
 
-     APPBARDATA appBarData;
 
-     appBarData.cbSize=sizeof(appBarData);
 
-     if (SHAppBarMessage(ABM_GETTASKBARPOS,&appBarData))
 
-     {
 
-         // We know the edge the taskbar is connected to, so guess the rect of the
 
-         // system tray. Use various fudge factor to make it look good
 
-         switch(appBarData.uEdge)
 
-         {
 
-         case ABE_LEFT:
 
-         case ABE_RIGHT:
 
-             // We want to minimize to the bottom of the taskbar
 
-             lprect->top    = appBarData.rc.bottom-100;
 
-             lprect->bottom = appBarData.rc.bottom-16;
 
-             lprect->left   = appBarData.rc.left;
 
-             lprect->right  = appBarData.rc.right;
 
-             break;
 
-             
 
-         case ABE_TOP:
 
-         case ABE_BOTTOM:
 
-             // We want to minimize to the right of the taskbar
 
-             lprect->top    = appBarData.rc.top;
 
-             lprect->bottom = appBarData.rc.bottom;
 
-             lprect->left   = appBarData.rc.right-100;
 
-             lprect->right  = appBarData.rc.right-16;
 
-             break;
 
-         }
 
-         return;
 
-     }
 
-     
 
-     // Blimey, we really aren't in luck. It's possible that a third party shell
 
-     // is running instead of explorer. This shell might provide support for the
 
-     // system tray, by providing a Shell_TrayWnd window (which receives the
 
-     // messages for the icons) So, look for a Shell_TrayWnd window and work out
 
-     // the rect from that. Remember that explorer's taskbar is the Shell_TrayWnd,
 
-     // and stretches either the width or the height of the screen. We can't rely
 
-     // on the 3rd party shell's Shell_TrayWnd doing the same, in fact, we can't
 
-     // rely on it being any size. The best we can do is just blindly use the
 
-     // window rect, perhaps limiting the width and height to, say 150 square.
 
-     // Note that if the 3rd party shell supports the same configuraion as
 
-     // explorer (the icons hosted in NotifyTrayWnd, which is a child window of
 
-     // Shell_TrayWnd), we would already have caught it above
 
-     if (hShellTrayWnd)
 
-     {
 
-         ::GetWindowRect(hShellTrayWnd, lprect);
 
-         if (lprect->right - lprect->left > DEFAULT_RECT_WIDTH)
 
-             lprect->left = lprect->right - DEFAULT_RECT_WIDTH;
 
-         if (lprect->bottom - lprect->top > DEFAULT_RECT_HEIGHT)
 
-             lprect->top = lprect->bottom - DEFAULT_RECT_HEIGHT;
 
-         
 
-         return;
 
-     }
 
-     
 
-     // OK. Haven't found a thing. Provide a default rect based on the current work
 
-     // area
 
-     SystemParametersInfo(SPI_GETWORKAREA,0, lprect, 0);
 
-     lprect->left = lprect->right - DEFAULT_RECT_WIDTH;
 
-     lprect->top  = lprect->bottom - DEFAULT_RECT_HEIGHT;
 
- }
 
- // Check to see if the animation has been disabled (Matthew Ellis <[email protected]>)
 
- BOOL CSystemTray::GetDoWndAnimation()
 
- {
 
- 	if(!m_bShowWndAnimation)
 
- 		return FALSE;
 
- 	
 
- 	ANIMATIONINFO ai;
 
- 	
 
- 	ai.cbSize=sizeof(ai);
 
- 	SystemParametersInfo(SPI_GETANIMATION,sizeof(ai),&ai,0);
 
- 	
 
- 	return ai.iMinAnimate?TRUE:FALSE;
 
- }
 
- #endif
 
- BOOL CSystemTray::RemoveTaskbarIcon(CWnd* pWnd)
 
- {
 
-     LPCTSTR pstrOwnerClass = AfxRegisterWndClass(0);
 
- 	
 
-     // Create static invisible window
 
-     if (!::IsWindow(m_wndInvisible.m_hWnd))
 
-     {
 
- 		if (!m_wndInvisible.CreateEx(0, pstrOwnerClass, _T(""), WS_POPUP,
 
- 			CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
 
- 			NULL, 0))
 
- 		{
 
- 			return FALSE;
 
- 		}
 
- 		
 
-     }
 
- 	
 
-     pWnd->SetParent(&m_wndInvisible);
 
- 	
 
-     return TRUE;
 
- }
 
- void CSystemTray::MinimiseToTray(CWnd* pWnd)
 
- {
 
- #ifndef _WIN32_WCE
 
-     if (GetDoWndAnimation())
 
-     {
 
-         CRect rectFrom, rectTo;
 
- 		
 
-         pWnd->GetWindowRect(rectFrom);
 
-         GetTrayWndRect(rectTo);
 
- 		
 
- 		::DrawAnimatedRects(pWnd->m_hWnd, IDANI_CAPTION, rectFrom, rectTo);
 
-     }
 
- 	
 
-     RemoveTaskbarIcon(pWnd);
 
-     pWnd->ModifyStyle(WS_VISIBLE, 0);
 
- #endif
 
- }
 
- void CSystemTray::MaximiseFromTray(CWnd* pWnd)
 
- {
 
- #ifndef _WIN32_WCE
 
-     if (GetDoWndAnimation())
 
-     {
 
-         CRect rectTo;
 
-         pWnd->GetWindowRect(rectTo);
 
-         CRect rectFrom;
 
-         GetTrayWndRect(rectFrom);
 
-         pWnd->SetParent(NULL);
 
- 		::DrawAnimatedRects(pWnd->m_hWnd, IDANI_CAPTION, rectFrom, rectTo);
 
-     }
 
-     else
 
-         pWnd->SetParent(NULL);
 
-     pWnd->ModifyStyle(0, WS_VISIBLE);
 
-     pWnd->RedrawWindow(NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN | RDW_FRAME |
 
-                                    RDW_INVALIDATE | RDW_ERASE);
 
-     // Move focus away and back again to ensure taskbar icon is recreated
 
-     if (::IsWindow(m_wndInvisible.m_hWnd))
 
-         m_wndInvisible.SetActiveWindow();
 
-     pWnd->SetActiveWindow();
 
-     pWnd->SetForegroundWindow();
 
- #endif
 
- }
 
 
  |