summaryrefslogtreecommitdiff
path: root/common/trayicon.h
diff options
context:
space:
mode:
Diffstat (limited to 'common/trayicon.h')
-rw-r--r--common/trayicon.h189
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