bool SendNotifyCallback(InternalIconData* notifyItem, UINT uMsg);
private:
+ LRESULT OnCtxMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
VOID SendMouseEvent(IN WORD wIndex, IN UINT uMsg, IN WPARAM wParam);
LRESULT OnMouseEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnTooltipShow(INT uCode, LPNMHDR hdr, BOOL& bHandled);
public:
BEGIN_MSG_MAP(CNotifyToolbar)
+ MESSAGE_HANDLER(WM_CONTEXTMENU, OnCtxMenu)
MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseEvent)
NOTIFY_CODE_HANDLER(TTN_SHOW, OnTooltipShow)
END_MSG_MAP()
void Initialize(HWND hWndParent, CBalloonQueue * queue);
};
-extern const WCHAR szSysPagerWndClass[];
+
+static const WCHAR szSysPagerWndClass[] = L"SysPager";
class CSysPagerWnd :
public CComCoClass<CSysPagerWnd>,
LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnGetInfoTip(INT uCode, LPNMHDR hdr, BOOL& bHandled);
LRESULT OnCustomDraw(INT uCode, LPNMHDR hdr, BOOL& bHandled);
+ LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnCtxMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnBalloonPop(UINT uCode, LPNMHDR hdr, BOOL& bHandled);
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
+ MESSAGE_HANDLER(WM_COMMAND, OnCommand)
MESSAGE_HANDLER(WM_SIZE, OnSize)
MESSAGE_HANDLER(WM_CONTEXTMENU, OnCtxMenu)
MESSAGE_HANDLER(WM_TIMER, OnTimer)
HRESULT Initialize(IN HWND hWndParent);
};
+/*
+ * IconWatcher
+ */
+
CIconWatcher::CIconWatcher() :
m_hWatcherThread(NULL),
m_WakeUpEvent(NULL),
}
/*
-* NotifyToolbar
-*/
+ * BalloonQueue
+ */
CBalloonQueue::CBalloonQueue() :
m_hwndParent(NULL),
SetButtonSize(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
}
+LRESULT CNotifyToolbar::OnCtxMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+ bHandled = FALSE;
+
+ /*
+ * WM_CONTEXTMENU message can be generated either by the mouse,
+ * in which case lParam encodes the mouse coordinates where the
+ * user right-clicked the mouse, or can be generated by (Shift-)F10
+ * keyboard press, in which case lParam equals -1.
+ */
+ INT iBtn = GetHotItem();
+ if (iBtn < 0)
+ return 0;
+
+ InternalIconData* notifyItem = GetItemData(iBtn);
+
+ if (!::IsWindow(notifyItem->hWnd))
+ return 0;
+
+ if (notifyItem->uVersionCopy >= NOTIFYICON_VERSION)
+ {
+ /* Transmit the WM_CONTEXTMENU message if the notification icon supports it */
+ ::SendNotifyMessage(notifyItem->hWnd,
+ notifyItem->uCallbackMessage,
+ notifyItem->uID,
+ WM_CONTEXTMENU);
+ }
+ else if (lParam == -1)
+ {
+ /*
+ * Otherwise, and only if the WM_CONTEXTMENU message was generated
+ * from the keyboard, simulate right-click mouse messages. This is
+ * not needed if the message came from the mouse because in this
+ * case the right-click mouse messages were already sent together.
+ */
+ ::SendNotifyMessage(notifyItem->hWnd,
+ notifyItem->uCallbackMessage,
+ notifyItem->uID,
+ WM_RBUTTONDOWN);
+ ::SendNotifyMessage(notifyItem->hWnd,
+ notifyItem->uCallbackMessage,
+ notifyItem->uID,
+ WM_RBUTTONUP);
+ }
+
+ return 0;
+}
+
bool CNotifyToolbar::SendNotifyCallback(InternalIconData* notifyItem, UINT uMsg)
{
if (!::IsWindow(notifyItem->hWnd))
}
else
{
- SendMessage(notifyItem->hWnd,
- notifyItem->uCallbackMessage,
- notifyItem->uID,
- uMsg);
+ ::SendMessage(notifyItem->hWnd,
+ notifyItem->uCallbackMessage,
+ notifyItem->uID,
+ uMsg);
}
return false;
}
LRESULT CNotifyToolbar::OnMouseEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
-
INT iBtn = HitTest(&pt);
if (iBtn >= 0)
/*
* SysPagerWnd
*/
-const WCHAR szSysPagerWndClass[] = L"SysPager";
CSysPagerWnd::CSysPagerWnd() {}
+
CSysPagerWnd::~CSysPagerWnd() {}
LRESULT CSysPagerWnd::OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
(void)AddIconToWatcher(iconData);
}
break;
+
case NIM_MODIFY:
ret = Toolbar.UpdateButton(iconData);
break;
+
case NIM_DELETE:
ret = Toolbar.RemoveButton(iconData);
if (ret == TRUE)
(void)RemoveIconFromWatcher(iconData);
}
break;
+
case NIM_SETFOCUS:
Toolbar.SetFocus();
ret = TRUE;
+ break;
+
case NIM_SETVERSION:
ret = Toolbar.SwitchVersion(iconData);
+ break;
+
default:
TRACE("NotifyIcon received with unknown code %d.\n", dwMessage);
return FALSE;
return TRUE;
}
+LRESULT CSysPagerWnd::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+ bHandled = FALSE;
+
+ /* Handles the BN_CLICKED notifications sent by the CNotifyToolbar member */
+ if (HIWORD(wParam) != BN_CLICKED)
+ return 0;
+
+ INT iBtn = LOWORD(wParam);
+ if (iBtn < 0)
+ return 0;
+
+ InternalIconData* notifyItem = Toolbar.GetItemData(iBtn);
+
+ if (!::IsWindow(notifyItem->hWnd))
+ return 0;
+
+ // TODO: Improve keyboard handling by looking whether one presses
+ // on ENTER, etc..., which roughly translates into "double-clicking".
+
+ if (notifyItem->uVersionCopy >= NOTIFYICON_VERSION)
+ {
+ /* Use new-style notifications if the notification icon supports them */
+ ::SendNotifyMessage(notifyItem->hWnd,
+ notifyItem->uCallbackMessage,
+ notifyItem->uID,
+ NIN_SELECT); // TODO: Distinguish with NIN_KEYSELECT
+ }
+ else if (lParam == -1)
+ {
+ /*
+ * Otherwise, and only if the icon was selected via the keyboard,
+ * simulate right-click mouse messages. This is not needed if the
+ * selection was done by mouse because in this case the mouse
+ * messages were already sent.
+ */
+ ::SendNotifyMessage(notifyItem->hWnd,
+ notifyItem->uCallbackMessage,
+ notifyItem->uID,
+ WM_LBUTTONDOWN); // TODO: Distinguish with double-click WM_LBUTTONDBLCLK
+ ::SendNotifyMessage(notifyItem->hWnd,
+ notifyItem->uCallbackMessage,
+ notifyItem->uID,
+ WM_LBUTTONUP);
+ }
+
+ return 0;
+}
+
LRESULT CSysPagerWnd::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
LRESULT Ret = TRUE;