//+---------------------------------------------------------------------------- // // File: trayicon.cpp // // Module: CMMON32.EXE // // Synopsis: Implementation for the CTrayIcon class. // // Copyright (c) 1998-1999 Microsoft Corporation // // Author: quintinb Created Header 08/16/99 // //+---------------------------------------------------------------------------- #include "cmmaster.h" #include "resource.h" #include "TrayIcon.h" #include "Monitor.h" #include "cm_misc.h" #include "ShellDll.h" //+---------------------------------------------------------------------------- // // Function: CTrayIcon::CTrayIcon // // Synopsis: Constructor // // Arguments: Nothing // // Returns: Nothing // // History: fengsun Created Header 2/17/98 // //+---------------------------------------------------------------------------- CTrayIcon::CTrayIcon() { m_hwnd = NULL; m_hMenu = m_hSubMenu = NULL; m_uID = 0; m_hIcon = NULL; } //+---------------------------------------------------------------------------- // // Function: CTrayIcon::~CTrayIcon // // Synopsis: Destructor // // Arguments: None // // Returns: Nothing // // History: Created Header 4/7/98 // //+---------------------------------------------------------------------------- CTrayIcon::~CTrayIcon() { if (m_hMenu) { DestroyMenu(m_hMenu); } if (m_hIcon) { DeleteObject(m_hIcon); } for (int i=0; i< m_CommandArray.GetSize();i++) { CmFree((TCHAR*) m_CommandArray[i]); } } #if 0 // this function is not used /* //+---------------------------------------------------------------------------- // // Function: CTrayIcon::SetTip // // Synopsis: Change the tip of the tray icon // // Arguments: const TCHAR* lpMsg - message to set // // Returns: Nothing // // History: fengsun Created Header 2/17/98 // //+---------------------------------------------------------------------------- void CTrayIcon::SetTip(const TCHAR* lpMsg) { MYDBGASSERT(IsWindow(m_hwnd)); MYDBGASSERT(lpMsg); NOTIFYICONDATA nidData; ZeroMemory(&nidData,sizeof(nidData)); nidData.cbSize = sizeof(nidData); nidData.hWnd = m_hwnd; nidData.uID = m_uID; nidData.uFlags = NIF_TIP; lstrcpyn(nidData.szTip,lpMsg,sizeof(nidData.szTip)/sizeof(TCHAR)); // // Load Shell32.dll and call Shell_NotifyIcon // CShellDll ShellDll; BOOL bRes = ShellDll.NotifyIcon(NIM_MODIFY,&nidData); MYDBGASSERT(bRes); } */ #endif //+---------------------------------------------------------------------------- // // Function: CTrayIcon::SetIcon // // Synopsis: Set the icon for the tray icon // // Arguments: HICON hIcon - icon to set. Use NULL to use existing icon. // HWND hwnd - window to receive tray icon message // UINT uMsg - tray icon message // UINT uID - The id for the tray icon // const TCHAR* lpMsg - The initial tip for the icon // // Returns: Nothing // // History: fengsun Created Header 2/17/98 // //+---------------------------------------------------------------------------- void CTrayIcon::SetIcon(HICON hIcon, HWND hwnd, UINT uMsg, UINT uID, const TCHAR* lpMsg) { MYDBGASSERT(IsWindow(hwnd)); //MYDBGASSERT(m_hIcon == NULL); //MYDBGASSERT(hIcon); MYDBGASSERT(m_hIcon == NULL && hIcon || m_hIcon && hIcon == NULL); m_hwnd = hwnd; m_uID = uID; NOTIFYICONDATA nidData; ZeroMemory(&nidData,sizeof(nidData)); nidData.cbSize = sizeof(nidData); nidData.hWnd = m_hwnd; nidData.uID = uID; nidData.uFlags = NIF_ICON | NIF_MESSAGE; // // we'll reuse the icon if we already have one. // if (!m_hIcon) { m_hIcon = hIcon; } nidData.hIcon = m_hIcon; nidData.uCallbackMessage = uMsg; if (lpMsg) { nidData.uFlags |= NIF_TIP; lstrcpynU(nidData.szTip,lpMsg,sizeof(nidData.szTip)/sizeof(TCHAR)); } // // Load Shell32.dll and call Shell_NotifyIcon // CShellDll ShellDll; DWORD cRetries = 0; BOOL bRes = ShellDll.NotifyIcon(NIM_ADD,&nidData); // // Check if Icon is already added // if (bRes == FALSE) { bRes = ShellDll.NotifyIcon(NIM_MODIFY,&nidData); } // // If this fails its very likely that the tray is not started yet. Retry few times // with a max wait time of 5 mins & then abort // while (bRes == FALSE && cRetries < 300) { Sleep(1000); cRetries ++; // CMTRACE1(TEXT("Shell_NotifyIcon = %d"), bRes); bRes = ShellDll.NotifyIcon(NIM_ADD,&nidData); // // Check if Icon is already added // if (bRes == FALSE) { bRes = ShellDll.NotifyIcon(NIM_MODIFY,&nidData); } } MYDBGASSERT(bRes); } //+---------------------------------------------------------------------------- // // Function: CTrayIcon::RemoveIcon // // Synopsis: remove icon from the tray // // Arguments: None // // Returns: Nothing // // History: fengsun Created Header 2/17/98 // //+---------------------------------------------------------------------------- void CTrayIcon::RemoveIcon() { if (m_hIcon) { NOTIFYICONDATA nidData; ZeroMemory(&nidData,sizeof(nidData)); nidData.cbSize = sizeof(nidData); nidData.hWnd = m_hwnd; nidData.uID = m_uID; // // Load Shell32.dll and call Shell_NotifyIcon // CShellDll ShellDll; BOOL bRes = ShellDll.NotifyIcon(NIM_DELETE,&nidData); MYDBGASSERT(bRes); DeleteObject(m_hIcon); m_hIcon = NULL; } } //+--------------------------------------------------------------------------- // // class CMultipleString // // Description: A string taht have multiple sub strings. // The format is "stringA\0stringB\0...\0\0" // // History: fengsun Created 2/17/98 // //---------------------------------------------------------------------------- class CMultipleString { public: CMultipleString(const TCHAR* lpStrings) {m_lpStrings = lpStrings;} const TCHAR* GetNextString(); protected: const TCHAR * m_lpStrings; // pointer to the string to be distracted }; //+---------------------------------------------------------------------------- // // Function: CMultipleString::GetNextString // // Synopsis: Get the next substring // // Arguments: None // // Returns: const TCHAR* - The next sub string or NULL // // History: fengsun Created Header 2/17/98 // //+---------------------------------------------------------------------------- const TCHAR* CMultipleString::GetNextString() { MYDBGASSERT(m_lpStrings); if (m_lpStrings[0] == TEXT('\0')) { // // Reach the end og the string // return NULL; } const TCHAR* lpReturn = m_lpStrings; // // Advance the pointer to the next string // m_lpStrings += lstrlenU(lpReturn)+1; return (lpReturn); } //+---------------------------------------------------------------------------- // // Function: CTrayIcon::CreateMenu // // Synopsis: Create the menu for the tray icon // // Arguments: const CIni* pIniFile - The ini file which have a tray menu section // DWORD dwMsgBase - The starting message id for the additional // command in the tray menu // // Returns: Nothing // // History: Created Header 2/17/98 // //+---------------------------------------------------------------------------- void CTrayIcon::CreateMenu(const CIni* pIniFile, DWORD dwMsgBase) { MYDBGASSERT(pIniFile); // // The default tray menu is the sub-menu of IDM_TRAY in the resource // m_hMenu = LoadMenuU(CMonitor::GetInstance(), MAKEINTRESOURCE(IDM_TRAY)); MYDBGASSERT(m_hMenu != NULL); m_hSubMenu = GetSubMenu(m_hMenu, 0); MYDBGASSERT(m_hSubMenu != NULL); // // lpMenuNames contains all the entry names under c_pszCmSectionMenuOptions // LPTSTR lpMenuNames = pIniFile->GPPS(c_pszCmSectionMenuOptions, (LPTSTR)NULL); if (lpMenuNames[0] == 0) { // // No additional menu item // CmFree(lpMenuNames); return; } int nMenuPos; // the position to insert menu; nMenuPos = GetMenuItemCount(m_hSubMenu); MYDBGASSERT(nMenuPos >= 0); // // Add seperator // MYVERIFY(FALSE != InsertMenuU(m_hSubMenu, nMenuPos, MF_BYPOSITION|MF_SEPARATOR, 0, 0)); nMenuPos++; // // append menus // CMultipleString MultipleStr(lpMenuNames); while(TRUE) { const TCHAR* lpMenuName = MultipleStr.GetNextString(); if (lpMenuName == NULL) { // // No more string // break; } LPTSTR lpCmdLine = pIniFile->GPPS(c_pszCmSectionMenuOptions,lpMenuName); MYDBGASSERT(lpCmdLine && lpCmdLine[0]); if (lpCmdLine[0] == 0) { // // Ignore menu without command line // CmFree(lpCmdLine); continue; } // // Add the command to the menu // MYVERIFY(FALSE != InsertMenuU(m_hSubMenu, nMenuPos, MF_BYPOSITION|MF_STRING, dwMsgBase + m_CommandArray.GetSize(), lpMenuName)); nMenuPos++; // // Add the command to the command array // m_CommandArray.Add(lpCmdLine); } CmFree(lpMenuNames); }