// // AUTHOR // Stef Walter // // LICENSE // This software is in the public domain. // // The software is provided "as is", without warranty of any kind, // express or implied, including but not limited to the warranties // of merchantability, fitness for a particular purpose, and // noninfringement. In no event shall the author(s) be liable for any // claim, damages, or other liability, whether in an action of // contract, tort, or otherwise, arising from, out of, or in connection // with the software or the use or other dealings in the software. // // SUPPORT // Send bug reports to: // #ifndef __TRAYICON_H__ #define __TRAYICON_H__ #include "mystring.h" //////////////////////////////////////////////////////////////// // CTrayIcon manages an icon in the Windows 95 system tray. // class CTrayIcon { public: CTrayIcon(UINT uID, HINSTANCE hInst) { // Initialize NOTIFYICONDATA memset(&m_nid, 0 , sizeof(m_nid)); m_nid.cbSize = sizeof(m_nid); m_nid.uID = uID; // never changes after construction m_uID = uID; m_hInst = hInst; m_bEnabled = true; string sTip; sTip.load_string(hInst, uID); _tcsncpy(m_nid.szTip, sTip, 63); m_nid.szTip[63] = 0; } ~CTrayIcon() { SetIcon(0); } // Call this to receive tray notifications void SetNotificationWnd(HWND hWndNotify, UINT uCbMsg) { ATLASSERT(hWndNotify == NULL || ::IsWindow(hWndNotify)); ATLASSERT(uCbMsg == 0 || uCbMsg >= WM_USER); m_nid.hWnd = hWndNotify; m_nid.uCallbackMessage = uCbMsg; } // SetIcon functions. To remove icon, call SetIcon(0) // main variant you want to use bool SetIcon(UINT uID) { string sTip; sTip.load_string(_Module.m_hInst, uID); return SetIcon(uID, sTip); } bool SetIcon(UINT uID, LPCSTR szTip) { HICON hicon = NULL; if (uID) { hicon = (HICON)::LoadImage(_Module.m_hInst, MAKEINTRESOURCE(uID), IMAGE_ICON, 16, 16, LR_SHARED); m_uID = uID; _tcsncpy(m_nid.szTip, szTip, 63); m_nid.szTip[63] = 0; } return SetIcon(hicon, NULL); } ////////////////// // Common SetIcon for all overloads. bool SetIcon(HICON hicon, LPCSTR lpTip) { UINT msg; m_nid.uFlags = 0; // Set the icon if (hicon) { // Add or replace icon in system tray msg = m_nid.hIcon ? NIM_MODIFY : NIM_ADD; m_nid.hIcon = hicon; m_nid.uFlags |= NIF_ICON; } else { // remove icon from tray if (m_nid.hIcon == NULL) return true; // already deleted msg = NIM_DELETE; } // Use the tip, if any if (lpTip) strncpy(m_nid.szTip, lpTip, sizeof(m_nid.szTip)); if (m_nid.szTip[0]) m_nid.uFlags |= NIF_TIP; // Use callback if any if (m_nid.uCallbackMessage && m_nid.hWnd) m_nid.uFlags |= NIF_MESSAGE; // Do it bool bRet = Shell_NotifyIcon(msg, &m_nid) ? true : false; if (msg == NIM_DELETE || !bRet) m_nid.hIcon = NULL; // failed return bRet; } bool SetStandardIcon(LPCTSTR lpszIconName, LPCSTR lpTip) { return SetIcon(::LoadIcon(NULL, lpszIconName), lpTip); } void Enable(bool bEnable = true) { m_bEnabled = bEnable; } LRESULT OnTrayNotification(WPARAM wID, LPARAM lEvent) { if (!m_bEnabled || wID != m_nid.uID || (lEvent != WM_RBUTTONUP && lEvent != WM_LBUTTONDBLCLK)) return 0; // If there's a resource menu with the same ID as the icon, use it as // the right-button popup menu. CTrayIcon will interprets the first // item in the menu as the default command for WM_LBUTTONDBLCLK // HMENU hMenu = ::LoadMenu(_Module.m_hInst, MAKEINTRESOURCE(m_uID)); if (!hMenu) return 0; HMENU hSubMenu = GetSubMenu(hMenu, 0); if (!hSubMenu) { DestroyMenu(hMenu); return 0; } if (lEvent==WM_RBUTTONUP) { // Make first menu item the default (bold font) ::SetMenuDefaultItem(hSubMenu, 0, TRUE); // Display the menu at the current mouse location. There's a "bug" // (Microsoft calls it a feature) in Windows 95 that requires calling // SetForegroundWindow. To find out more, search for Q135788 in MSDN. // POINT ptMouse; ::GetCursorPos(&ptMouse); ::SetForegroundWindow(m_nid.hWnd); ::TrackPopupMenu(hSubMenu, 0, ptMouse.x, ptMouse.y, 0, m_nid.hWnd, NULL); } else // double click: execute first menu item ::SendMessage(m_nid.hWnd, WM_COMMAND, ::GetMenuItemID(hSubMenu, 0), 0); // TODO: Let's see if we need this // DestroyMenu(hSubMenu); return 1; // handled } protected: NOTIFYICONDATA m_nid; // struct for Shell_NotifyIcon args UINT m_uID; HINSTANCE m_hInst; bool m_bEnabled; }; #endif //_TRAYICON_H_991016