#include "precomp.h"
-// Data comes from shell32/systray.cpp -> TrayNotifyCDS_Dummy
-typedef struct _SYS_PAGER_COPY_DATA
+struct InternalIconData : NOTIFYICONDATA
{
- DWORD cookie;
- DWORD notify_code;
- NOTIFYICONDATA nicon_data;
-} SYS_PAGER_COPY_DATA, *PSYS_PAGER_COPY_DATA;
+ // Must keep a separate copy since the original is unioned with uTimeout.
+ UINT uVersionCopy;
+};
+
+struct IconWatcherData
+{
+ HANDLE hProcess;
+ DWORD ProcessId;
+ NOTIFYICONDATA IconData;
+
+ IconWatcherData(CONST NOTIFYICONDATA *iconData) :
+ hProcess(NULL), ProcessId(0)
+ {
+ IconData.cbSize = sizeof(NOTIFYICONDATA);
+ IconData.hWnd = iconData->hWnd;
+ IconData.uID = iconData->uID;
+ IconData.guidItem = iconData->guidItem;
+ }
+
+ ~IconWatcherData()
+ {
+ if (hProcess)
+ {
+ CloseHandle(hProcess);
+ }
+ }
+};
+
+class CIconWatcher
+{
+ CAtlList<IconWatcherData *> m_WatcherList;
+ CRITICAL_SECTION m_ListLock;
+ HANDLE m_hWatcherThread;
+ HANDLE m_WakeUpEvent;
+ HWND m_hwndSysTray;
+ bool m_Loop;
+
+public:
+ CIconWatcher();
+
+ virtual ~CIconWatcher();
+
+ bool Initialize(_In_ HWND hWndParent);
+ void Uninitialize();
+
+ bool AddIconToWatcher(_In_ CONST NOTIFYICONDATA *iconData);
+ bool RemoveIconFromWatcher(_In_ CONST NOTIFYICONDATA *iconData);
+
+ IconWatcherData* GetListEntry(_In_opt_ CONST NOTIFYICONDATA *iconData, _In_opt_ HANDLE hProcess, _In_ bool Remove);
+
+private:
+
+ static UINT WINAPI WatcherThread(_In_opt_ LPVOID lpParam);
+};
+
+class CNotifyToolbar;
+
+class CBalloonQueue
+{
+public:
+ static const int TimerInterval = 2000;
+ static const int BalloonsTimerId = 1;
+ static const int MinTimeout = 10000;
+ static const int MaxTimeout = 30000;
+ static const int CooldownBetweenBalloons = 2000;
+
+private:
+ struct Info
+ {
+ InternalIconData * pSource;
+ WCHAR szInfo[256];
+ WCHAR szInfoTitle[64];
+ WPARAM uIcon;
+ UINT uTimeout;
+
+ Info(InternalIconData * source)
+ {
+ pSource = source;
+ StringCchCopy(szInfo, _countof(szInfo), source->szInfo);
+ StringCchCopy(szInfoTitle, _countof(szInfoTitle), source->szInfoTitle);
+ uIcon = source->dwInfoFlags & NIIF_ICON_MASK;
+ if (source->dwInfoFlags == NIIF_USER)
+ uIcon = reinterpret_cast<WPARAM>(source->hIcon);
+ uTimeout = source->uTimeout;
+ }
+ };
+
+ HWND m_hwndParent;
+
+ CTooltips * m_tooltips;
+
+ CAtlList<Info> m_queue;
+
+ CNotifyToolbar * m_toolbar;
+
+ InternalIconData * m_current;
+ bool m_currentClosed;
+
+ int m_timer;
+
+public:
+ CBalloonQueue();
+
+ void Init(HWND hwndParent, CNotifyToolbar * toolbar, CTooltips * balloons);
+ void Deinit();
+
+ bool OnTimer(int timerId);
+ void UpdateInfo(InternalIconData * notifyItem);
+ void RemoveInfo(InternalIconData * notifyItem);
+ void CloseCurrent();
+
+private:
+
+ int IndexOf(InternalIconData * pdata);
+ void SetTimer(int length);
+ void Show(Info& info);
+ void Close(IN OUT InternalIconData * notifyItem, IN UINT uReason);
+};
+
+class CNotifyToolbar :
+ public CWindowImplBaseT< CToolbar<InternalIconData>, CControlWinTraits >
+{
+ HIMAGELIST m_ImageList;
+ int m_VisibleButtonCount;
+
+ CBalloonQueue * m_BalloonQueue;
+
+public:
+ CNotifyToolbar();
+ virtual ~CNotifyToolbar();
+
+ int GetVisibleButtonCount();
+ int FindItem(IN HWND hWnd, IN UINT uID, InternalIconData ** pdata);
+ int FindExistingSharedIcon(HICON handle);
+ BOOL AddButton(IN CONST NOTIFYICONDATA *iconData);
+ BOOL SwitchVersion(IN CONST NOTIFYICONDATA *iconData);
+ BOOL UpdateButton(IN CONST NOTIFYICONDATA *iconData);
+ BOOL RemoveButton(IN CONST NOTIFYICONDATA *iconData);
+ VOID ResizeImagelist();
+ bool SendNotifyCallback(InternalIconData* notifyItem, UINT uMsg);
+
+private:
+ 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_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[];
+
+class CSysPagerWnd :
+ public CComCoClass<CSysPagerWnd>,
+ public CComObjectRootEx<CComMultiThreadModelNoCS>,
+ public CWindowImpl < CSysPagerWnd, CWindow, CControlWinTraits >,
+ public IOleWindow,
+ public CIconWatcher
+{
+ CNotifyToolbar Toolbar;
+ CTooltips m_Balloons;
+ CBalloonQueue m_BalloonQueue;
+
+public:
+ CSysPagerWnd();
+ virtual ~CSysPagerWnd();
+
+ LRESULT DrawBackground(HDC hdc);
+ LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+ LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+ 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 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);
+ LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+ LRESULT OnCopyData(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+ LRESULT OnSettingChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+ LRESULT OnGetMinimumSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+
+public:
+
+ HRESULT WINAPI GetWindow(HWND* phwnd)
+ {
+ if (!phwnd)
+ return E_INVALIDARG;
+ *phwnd = m_hWnd;
+ return S_OK;
+ }
+
+ HRESULT WINAPI ContextSensitiveHelp(BOOL fEnterMode)
+ {
+ return E_NOTIMPL;
+ }
+
+ DECLARE_NOT_AGGREGATABLE(CSysPagerWnd)
+
+ DECLARE_PROTECT_FINAL_CONSTRUCT()
+ BEGIN_COM_MAP(CSysPagerWnd)
+ COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
+ END_COM_MAP()
+
+ BOOL NotifyIcon(DWORD dwMessage, _In_ CONST NOTIFYICONDATA *iconData);
+ void GetSize(IN BOOL IsHorizontal, IN PSIZE size);
+
+ DECLARE_WND_CLASS_EX(szSysPagerWndClass, CS_DBLCLKS, COLOR_3DFACE)
+
+ BEGIN_MSG_MAP(CSysPagerWnd)
+ MESSAGE_HANDLER(WM_CREATE, OnCreate)
+ MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
+ MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
+ MESSAGE_HANDLER(WM_SIZE, OnSize)
+ MESSAGE_HANDLER(WM_CONTEXTMENU, OnCtxMenu)
+ MESSAGE_HANDLER(WM_TIMER, OnTimer)
+ MESSAGE_HANDLER(WM_COPYDATA, OnCopyData)
+ MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChanged)
+ MESSAGE_HANDLER(TNWM_GETMINIMUMSIZE, OnGetMinimumSize)
+ NOTIFY_CODE_HANDLER(TTN_POP, OnBalloonPop)
+ NOTIFY_CODE_HANDLER(TBN_GETINFOTIPW, OnGetInfoTip)
+ NOTIFY_CODE_HANDLER(NM_CUSTOMDRAW, OnCustomDraw)
+ END_MSG_MAP()
+
+ HRESULT Initialize(IN HWND hWndParent);
+};
CIconWatcher::CIconWatcher() :
m_hWatcherThread(NULL),
LeaveCriticalSection(&m_ListLock);
}
-bool CIconWatcher::AddIconToWatcher(_In_ NOTIFYICONDATA *iconData)
+bool CIconWatcher::AddIconToWatcher(_In_ CONST NOTIFYICONDATA *iconData)
{
DWORD ProcessId;
(void)GetWindowThreadProcessId(iconData->hWnd, &ProcessId);
IconWatcherData *Icon = new IconWatcherData(iconData);
Icon->hProcess = hProcess;
- Icon->ProcessId;
+ Icon->ProcessId = ProcessId;
bool Added = false;
EnterCriticalSection(&m_ListLock);
return Added;
}
-bool CIconWatcher::RemoveIconFromWatcher(_In_ NOTIFYICONDATA *iconData)
+bool CIconWatcher::RemoveIconFromWatcher(_In_ CONST NOTIFYICONDATA *iconData)
{
EnterCriticalSection(&m_ListLock);
return true;
}
-IconWatcherData* CIconWatcher::GetListEntry(_In_opt_ NOTIFYICONDATA *iconData, _In_opt_ HANDLE hProcess, _In_ bool Remove)
+IconWatcherData* CIconWatcher::GetListEntry(_In_opt_ CONST NOTIFYICONDATA *iconData, _In_opt_ HANDLE hProcess, _In_ bool Remove)
{
IconWatcherData *Entry = NULL;
POSITION NextPosition = m_WatcherList.GetHeadPosition();
ASSERT(Size <= MAXIMUM_WAIT_OBJECTS);
if (WatchList)
- delete WatchList;
+ delete[] WatchList;
WatchList = new HANDLE[Size];
WatchList[0] = This->m_WakeUpEvent;
TRACE("Pid %lu owns a notification icon and has stopped without deleting it. We'll cleanup on its behalf", Icon->ProcessId);
- int len = FIELD_OFFSET(SYS_PAGER_COPY_DATA, nicon_data) + Icon->IconData.cbSize;
- PSYS_PAGER_COPY_DATA pnotify_data = (PSYS_PAGER_COPY_DATA)new BYTE[len];
- pnotify_data->cookie = 1;
- pnotify_data->notify_code = NIM_DELETE;
- memcpy(&pnotify_data->nicon_data, &Icon->IconData, Icon->IconData.cbSize);
+ TRAYNOTIFYDATAW tnid = {0};
+ tnid.dwSignature = NI_NOTIFY_SIG;
+ tnid.dwMessage = NIM_DELETE;
+ CopyMemory(&tnid.nid, &Icon->IconData, Icon->IconData.cbSize);
COPYDATASTRUCT data;
data.dwData = 1;
- data.cbData = len;
- data.lpData = pnotify_data;
-
- BOOL Success = FALSE;
- HWND parentHWND = ::GetParent(GetParent(This->m_hwndSysTray));
- if (parentHWND)
- Success = ::SendMessage(parentHWND, WM_COPYDATA, (WPARAM)&Icon->IconData, (LPARAM)&data);
-
- delete pnotify_data;
+ data.cbData = sizeof(tnid);
+ data.lpData = &tnid;
+ BOOL Success = ::SendMessage(This->m_hwndSysTray, WM_COPYDATA,
+ (WPARAM)&Icon->IconData, (LPARAM)&data);
if (!Success)
{
// If we failed to handle the delete message, forcibly remove it
}
if (WatchList)
- delete WatchList;
+ delete[] WatchList;
return 0;
}
{
}
-void CBalloonQueue::Init(HWND hwndParent, CToolbar<InternalIconData> * toolbar, CTooltips * balloons)
+void CBalloonQueue::Init(HWND hwndParent, CNotifyToolbar * toolbar, CTooltips * balloons)
{
m_hwndParent = hwndParent;
m_toolbar = toolbar;
if (m_current && !m_currentClosed)
{
- Close(m_current);
+ Close(m_current, NIN_BALLOONTIMEOUT);
}
else
{
}
else
{
- Close(notifyItem);
+ Close(notifyItem, NIN_BALLOONHIDE);
}
}
void CBalloonQueue::RemoveInfo(InternalIconData * notifyItem)
{
- Close(notifyItem);
+ Close(notifyItem, NIN_BALLOONHIDE);
POSITION position = m_queue.GetHeadPosition();
while(position != NULL)
void CBalloonQueue::CloseCurrent()
{
if (m_current != NULL)
- Close(m_current);
+ {
+ Close(m_current, NIN_BALLOONTIMEOUT);
+ }
}
int CBalloonQueue::IndexOf(InternalIconData * pdata)
if (timeout > MaxTimeout) timeout = MaxTimeout;
SetTimer(timeout);
+
+ m_toolbar->SendNotifyCallback(m_current, NIN_BALLOONSHOW);
}
-void CBalloonQueue::Close(IN OUT InternalIconData * notifyItem)
+void CBalloonQueue::Close(IN OUT InternalIconData * notifyItem, IN UINT uReason)
{
TRACE("HideBalloonTip called\n");
if (m_current == notifyItem && !m_currentClosed)
{
+ m_toolbar->SendNotifyCallback(m_current, uReason);
+
// Prevent Re-entry
m_currentClosed = true;
m_tooltips->TrackDeactivate();
return -1;
}
-BOOL CNotifyToolbar::AddButton(IN CONST NOTIFYICONDATA *iconData)
+BOOL CNotifyToolbar::AddButton(_In_ CONST NOTIFYICONDATA *iconData)
{
- TBBUTTON tbBtn;
+ TBBUTTON tbBtn = { 0 };
InternalIconData * notifyItem;
WCHAR text[] = L"";
if (iconData->uFlags & NIF_INFO)
{
// NOTE: In Vista+, the uTimeout value is disregarded, and the accessibility settings are used always.
- StrNCpy(notifyItem->szInfo, iconData->szInfo, _countof(notifyItem->szInfo));
- StrNCpy(notifyItem->szInfoTitle, iconData->szInfoTitle, _countof(notifyItem->szInfo));
+ StringCchCopy(notifyItem->szInfo, _countof(notifyItem->szInfo), iconData->szInfo);
+ StringCchCopy(notifyItem->szInfoTitle, _countof(notifyItem->szInfoTitle), iconData->szInfoTitle);
notifyItem->dwInfoFlags = iconData->dwInfoFlags;
notifyItem->uTimeout = iconData->uTimeout;
}
return TRUE;
}
-BOOL CNotifyToolbar::SwitchVersion(IN CONST NOTIFYICONDATA *iconData)
+BOOL CNotifyToolbar::SwitchVersion(_In_ CONST NOTIFYICONDATA *iconData)
{
InternalIconData * notifyItem;
int index = FindItem(iconData->hWnd, iconData->uID, ¬ifyItem);
return TRUE;
}
-BOOL CNotifyToolbar::UpdateButton(IN CONST NOTIFYICONDATA *iconData)
+BOOL CNotifyToolbar::UpdateButton(_In_ CONST NOTIFYICONDATA *iconData)
{
InternalIconData * notifyItem;
TBBUTTONINFO tbbi = { 0 };
if (iconData->uFlags & NIF_INFO)
{
// NOTE: In Vista+, the uTimeout value is disregarded, and the accessibility settings are used always.
- StrNCpy(notifyItem->szInfo, iconData->szInfo, _countof(notifyItem->szInfo));
- StrNCpy(notifyItem->szInfoTitle, iconData->szInfoTitle, _countof(notifyItem->szInfo));
+ StringCchCopy(notifyItem->szInfo, _countof(notifyItem->szInfo), iconData->szInfo);
+ StringCchCopy(notifyItem->szInfoTitle, _countof(notifyItem->szInfoTitle), iconData->szInfoTitle);
notifyItem->dwInfoFlags = iconData->dwInfoFlags;
notifyItem->uTimeout = iconData->uTimeout;
}
return TRUE;
}
-BOOL CNotifyToolbar::RemoveButton(IN CONST NOTIFYICONDATA *iconData)
+BOOL CNotifyToolbar::RemoveButton(_In_ CONST NOTIFYICONDATA *iconData)
{
InternalIconData * notifyItem;
SetButtonSize(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
}
-VOID CNotifyToolbar::SendMouseEvent(IN WORD wIndex, IN UINT uMsg, IN WPARAM wParam)
+bool CNotifyToolbar::SendNotifyCallback(InternalIconData* notifyItem, UINT uMsg)
{
- static LPCWSTR eventNames [] = {
- L"WM_MOUSEMOVE",
- L"WM_LBUTTONDOWN",
- L"WM_LBUTTONUP",
- L"WM_LBUTTONDBLCLK",
- L"WM_RBUTTONDOWN",
- L"WM_RBUTTONUP",
- L"WM_RBUTTONDBLCLK",
- L"WM_MBUTTONDOWN",
- L"WM_MBUTTONUP",
- L"WM_MBUTTONDBLCLK",
- L"WM_MOUSEWHEEL",
- L"WM_XBUTTONDOWN",
- L"WM_XBUTTONUP",
- L"WM_XBUTTONDBLCLK"
- };
-
- InternalIconData * notifyItem = GetItemData(wIndex);
-
if (!::IsWindow(notifyItem->hWnd))
{
// We detect and destroy icons with invalid handles only on mouse move over systray, same as MS does.
RemoveButton(notifyItem);
- HWND parentHWND = ::GetParent(::GetParent(GetParent()));
- ::SendMessage(parentHWND, WM_SIZE, 0, 0);
+ /* Ask the parent to resize */
+ NMHDR nmh = {GetParent(), 0, NTNWM_REALIGN};
+ GetParent().SendMessage(WM_NOTIFY, 0, (LPARAM) &nmh);
- return;
- }
-
- if (uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST)
- {
- TRACE("Sending message %S from button %d to %p (msg=%x, w=%x, l=%x)...\n",
- eventNames[uMsg - WM_MOUSEFIRST], wIndex,
- notifyItem->hWnd, notifyItem->uCallbackMessage, notifyItem->uID, uMsg);
+ return true;
}
DWORD pid;
(uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST))
{
::PostMessage(notifyItem->hWnd,
- notifyItem->uCallbackMessage,
- notifyItem->uID,
- uMsg);
+ notifyItem->uCallbackMessage,
+ notifyItem->uID,
+ uMsg);
}
else
{
notifyItem->uID,
uMsg);
}
+ return false;
+}
+
+VOID CNotifyToolbar::SendMouseEvent(IN WORD wIndex, IN UINT uMsg, IN WPARAM wParam)
+{
+ static LPCWSTR eventNames [] = {
+ L"WM_MOUSEMOVE",
+ L"WM_LBUTTONDOWN",
+ L"WM_LBUTTONUP",
+ L"WM_LBUTTONDBLCLK",
+ L"WM_RBUTTONDOWN",
+ L"WM_RBUTTONUP",
+ L"WM_RBUTTONDBLCLK",
+ L"WM_MBUTTONDOWN",
+ L"WM_MBUTTONUP",
+ L"WM_MBUTTONDBLCLK",
+ L"WM_MOUSEWHEEL",
+ L"WM_XBUTTONDOWN",
+ L"WM_XBUTTONUP",
+ L"WM_XBUTTONDBLCLK"
+ };
+
+ InternalIconData * notifyItem = GetItemData(wIndex);
+
+ if (uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST)
+ {
+ TRACE("Sending message %S from button %d to %p (msg=%x, w=%x, l=%x)...\n",
+ eventNames[uMsg - WM_MOUSEFIRST], wIndex,
+ notifyItem->hWnd, notifyItem->uCallbackMessage, notifyItem->uID, uMsg);
+ }
+
+ SendNotifyCallback(notifyItem, uMsg);
}
LRESULT CNotifyToolbar::OnMouseEvent(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
tbm.dwMask = TBMF_BARPAD | TBMF_BUTTONSPACING | TBMF_PAD;
tbm.cxPad = 1;
tbm.cyPad = 1;
+ tbm.cxBarPad = 1;
+ tbm.cyBarPad = 1;
tbm.cxButtonSpacing = 1;
tbm.cyButtonSpacing = 1;
SetMetrics(&tbm);
const WCHAR szSysPagerWndClass[] = L"SysPager";
CSysPagerWnd::CSysPagerWnd() {}
-CSysPagerWnd::~CSysPagerWnd() {}
-LRESULT CSysPagerWnd::DrawBackground(HDC hdc)
-{
- RECT rect;
-
- GetClientRect(&rect);
- DrawThemeParentBackground(m_hWnd, hdc, &rect);
-
- return TRUE;
-}
+CSysPagerWnd::~CSysPagerWnd() {}
LRESULT CSysPagerWnd::OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
return 0;
}
- return DrawBackground(hdc);
+ RECT rect;
+ GetClientRect(&rect);
+ DrawThemeParentBackground(m_hWnd, hdc, &rect);
+
+ return TRUE;
}
LRESULT CSysPagerWnd::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
return TRUE;
}
-BOOL CSysPagerWnd::NotifyIconCmd(WPARAM wParam, LPARAM lParam)
+BOOL CSysPagerWnd::NotifyIcon(DWORD dwMessage, _In_ CONST NOTIFYICONDATA *iconData)
{
- PCOPYDATASTRUCT cpData = (PCOPYDATASTRUCT) lParam;
- if (cpData->dwData == 1)
- {
- SYS_PAGER_COPY_DATA * data;
- NOTIFYICONDATA *iconData;
- BOOL ret = FALSE;
-
- int VisibleButtonCount = Toolbar.GetVisibleButtonCount();
+ BOOL ret = FALSE;
- data = (PSYS_PAGER_COPY_DATA) cpData->lpData;
- iconData = &data->nicon_data;
+ int VisibleButtonCount = Toolbar.GetVisibleButtonCount();
- TRACE("NotifyIconCmd received. Code=%d\n", data->notify_code);
- switch (data->notify_code)
+ TRACE("NotifyIcon received. Code=%d\n", dwMessage);
+ switch (dwMessage)
+ {
+ case NIM_ADD:
+ ret = Toolbar.AddButton(iconData);
+ if (ret == TRUE)
{
- case NIM_ADD:
- ret = Toolbar.AddButton(iconData);
- if (ret == TRUE)
- {
- (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;
- case NIM_SETVERSION:
- ret = Toolbar.SwitchVersion(iconData);
- default:
- TRACE("NotifyIconCmd received with unknown code %d.\n", data->notify_code);
- return FALSE;
+ (void)AddIconToWatcher(iconData);
}
+ break;
+
+ case NIM_MODIFY:
+ ret = Toolbar.UpdateButton(iconData);
+ break;
- if (VisibleButtonCount != Toolbar.GetVisibleButtonCount())
+ case NIM_DELETE:
+ ret = Toolbar.RemoveButton(iconData);
+ if (ret == TRUE)
{
- HWND parentHWND = ::GetParent(GetParent());
- ::SendMessage(parentHWND, WM_SIZE, 0, 0);
+ (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 ret;
+ if (VisibleButtonCount != Toolbar.GetVisibleButtonCount())
+ {
+ /* Ask the parent to resize */
+ NMHDR nmh = {GetParent(), 0, NTNWM_REALIGN};
+ GetParent().SendMessage(WM_NOTIFY, 0, (LPARAM) &nmh);
}
- return TRUE;
+ return ret;
}
void CSysPagerWnd::GetSize(IN BOOL IsHorizontal, IN PSIZE size)
return 0;
}
-void CSysPagerWnd::ResizeImagelist()
+LRESULT CSysPagerWnd::OnCopyData(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
- Toolbar.ResizeImagelist();
+ PCOPYDATASTRUCT cpData = (PCOPYDATASTRUCT)lParam;
+ if (cpData->dwData == 1)
+ {
+ /* A taskbar NotifyIcon notification */
+ PTRAYNOTIFYDATAW pData = (PTRAYNOTIFYDATAW)cpData->lpData;
+ if (pData->dwSignature == NI_NOTIFY_SIG)
+ return NotifyIcon(pData->dwMessage, &pData->nid);
+ }
+ // TODO: Handle other types of taskbar notifications
+
+ return FALSE;
+}
+
+LRESULT CSysPagerWnd::OnSettingChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+{
+ if (wParam == SPI_SETNONCLIENTMETRICS)
+ {
+ Toolbar.ResizeImagelist();
+ }
+ return 0;
}
-HWND CSysPagerWnd::_Init(IN HWND hWndParent, IN BOOL bVisible)
+LRESULT CSysPagerWnd::OnGetMinimumSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
- DWORD dwStyle;
+ GetSize((BOOL)wParam, (PSIZE)lParam);
+ return 0;
+}
+HRESULT CSysPagerWnd::Initialize(IN HWND hWndParent)
+{
/* Create the window. The tray window is going to move it to the correct
position and resize it as needed. */
- dwStyle = WS_CHILD | WS_CLIPSIBLINGS;
- if (bVisible)
- dwStyle |= WS_VISIBLE;
-
+ DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE;
Create(hWndParent, 0, NULL, dwStyle);
-
if (!m_hWnd)
- {
- return NULL;
- }
+ return E_FAIL;
SetWindowTheme(m_hWnd, L"TrayNotify", NULL);
- return m_hWnd;
+ return S_OK;
+}
+
+HRESULT CSysPagerWnd_CreateInstance(HWND hwndParent, REFIID riid, void **ppv)
+{
+ return ShellObjectCreatorInit<CSysPagerWnd>(hwndParent, riid, ppv);
}