diff options
Diffstat (limited to 'common/trayicon.h')
-rw-r--r-- | common/trayicon.h | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/common/trayicon.h b/common/trayicon.h new file mode 100644 index 0000000..8d01998 --- /dev/null +++ b/common/trayicon.h @@ -0,0 +1,189 @@ +// +// AUTHOR +// N. Nielsen +// +// 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: <nielsen@memberwebs.com> +// + +#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 |