#include "precomp.h"
-#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
-#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
-
/*
* SysPagerWnd
*/
-static const WCHAR szSysPagerWndClass [] = TEXT("SysPager");
+static const WCHAR szSysPagerWndClass [] = L"SysPager";
// Data comes from shell32/systray.cpp -> TrayNotifyCDS_Dummy
typedef struct _SYS_PAGER_COPY_DATA
} SYS_PAGER_COPY_DATA, *PSYS_PAGER_COPY_DATA;
class CNotifyToolbar :
- public CToolbar<NOTIFYICONDATA>
+ public CWindowImplBaseT< CToolbar<NOTIFYICONDATA>, CControlWinTraits >
{
static const int ICON_SIZE = 16;
{
TBBUTTON tbBtn;
NOTIFYICONDATA * notifyItem;
- WCHAR text [] = TEXT("");
+ WCHAR text[] = L"";
int index = FindItemByIconData(iconData, ¬ifyItem);
if (index >= 0)
if (iconData->uFlags & NIF_ICON)
{
tbbi.dwMask |= TBIF_IMAGE;
- tbbi.iImage = ImageList_AddIcon(m_ImageList, iconData->hIcon);
+ tbbi.iImage = ImageList_ReplaceIcon(m_ImageList, index, iconData->hIcon);
}
if (iconData->uFlags & NIF_TIP)
if (index < 0)
return FALSE;
- DeleteButton(index);
-
if (!(notifyItem->dwState & NIS_HIDDEN))
{
m_VisibleButtonCount--;
delete notifyItem;
+ ImageList_Remove(m_ImageList, index);
+
+ int count = GetButtonCount();
+
+ /* shift all buttons one index to the left -- starting one index right
+ from item to delete -- to preserve their correct icon and tip */
+ for (int i = index; i < count - 1; i++)
+ {
+ notifyItem = GetItemData(i + 1);
+ SetItemData(i, notifyItem);
+ UpdateButton(notifyItem);
+ }
+
+ /* Delete the right-most, now obsolete button */
+ DeleteButton(count - 1);
+
return TRUE;
}
NOTIFYICONDATA * 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.
+ // Alternatively we could search for them periodically (would waste more resources).
+ TRACE("destroying icon with invalid handle\n");
+
+ HWND parentHWND = GetParent();
+ parentHWND = ::GetParent(parentHWND);
+
+ RECT windowRect;
+ ::GetClientRect(parentHWND, &windowRect);
+
+ RemoveButton(notifyItem);
+
+ SendMessage(parentHWND,
+ WM_SIZE,
+ 0,
+ MAKELONG(windowRect.right - windowRect.left,
+ windowRect.bottom - windowRect.top));
+
return;
+ }
if (uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST)
{
if (pid == GetCurrentProcessId() ||
(uMsg >= WM_MOUSEFIRST && uMsg <= WM_MOUSELAST))
{
- PostMessage(notifyItem->hWnd,
- notifyItem->uCallbackMessage,
- notifyItem->uID,
- uMsg);
+ ::PostMessage(notifyItem->hWnd,
+ notifyItem->uCallbackMessage,
+ notifyItem->uID,
+ uMsg);
}
else
{
LRESULT 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)
LRESULT OnTooltipShow(INT uCode, LPNMHDR hdr, BOOL& bHandled)
{
RECT rcTip, rcItem;
- GetWindowRect(hdr->hwndFrom, &rcTip);
+ ::GetWindowRect(hdr->hwndFrom, &rcTip);
SIZE szTip = { rcTip.right - rcTip.left, rcTip.bottom - rcTip.top };
if (hMon)
GetMonitorInfo(hMon, &monInfo);
else
- GetWindowRect(GetDesktopWindow(), &monInfo.rcMonitor);
+ ::GetWindowRect(GetDesktopWindow(), &monInfo.rcMonitor);
GetItemRect(iBtn, &rcItem);
POINT ptItem = { rcItem.left, rcItem.top };
SIZE szItem = { rcItem.right - rcItem.left, rcItem.bottom - rcItem.top };
- ClientToScreen(m_hWnd, &ptItem);
+ ClientToScreen(&ptItem);
ptItem.x += szItem.cx / 2;
ptItem.y -= szTip.cy;
TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | TBSTYLE_WRAPABLE | TBSTYLE_TRANSPARENT |
CCS_TOP | CCS_NORESIZE | CCS_NOPARENTALIGN | CCS_NODIVIDER;
- SubclassWindow(Create(hWndParent, styles));
+ SubclassWindow(CToolbar::Create(hWndParent, styles));
SetWindowTheme(m_hWnd, L"TrayNotify", NULL);
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
Toolbar.Initialize(m_hWnd);
+
+ // Explicitly request running applications to re-register their systray icons
+ ::SendNotifyMessageW(HWND_BROADCAST,
+ RegisterWindowMessageW(L"TaskbarCreated"),
+ 0, 0);
+
return TRUE;
}
- LRESULT NotifyMsg(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+ BOOL NotifyIconCmd(WPARAM wParam, LPARAM lParam)
{
PCOPYDATASTRUCT cpData = (PCOPYDATASTRUCT) lParam;
if (cpData->dwData == 1)
NOTIFYICONDATA *iconData;
HWND parentHWND;
RECT windowRect;
+ BOOL ret = FALSE;
parentHWND = GetParent();
parentHWND = ::GetParent(parentHWND);
::GetClientRect(parentHWND, &windowRect);
data = (PSYS_PAGER_COPY_DATA) cpData->lpData;
iconData = &data->nicon_data;
+ TRACE("NotifyIconCmd received. Code=%d\n", data->notify_code);
switch (data->notify_code)
{
case NIM_ADD:
- return Toolbar.AddButton(iconData);
+ ret = Toolbar.AddButton(iconData);
+ break;
case NIM_MODIFY:
- return Toolbar.UpdateButton(iconData);
+ ret = Toolbar.UpdateButton(iconData);
+ break;
case NIM_DELETE:
- return Toolbar.RemoveButton(iconData);
- default:
- TRACE("NotifyMessage received with unknown code %d.\n", data->notify_code);
+ ret = Toolbar.RemoveButton(iconData);
break;
+ default:
+ TRACE("NotifyIconCmd received with unknown code %d.\n", data->notify_code);
+ return FALSE;
}
+
SendMessage(parentHWND,
WM_SIZE,
0,
MAKELONG(windowRect.right - windowRect.left,
- windowRect.bottom - windowRect.top));
+ windowRect.bottom - windowRect.top));
+
+ return ret;
}
return TRUE;
* TrayClockWnd
*/
-static const WCHAR szTrayClockWndClass [] = TEXT("TrayClockWClass");
+static const WCHAR szTrayClockWndClass[] = L"TrayClockWClass";
#define ID_TRAYCLOCK_TIMER 0
#define ID_TRAYCLOCK_TIMER_INIT 1
{
BOOL IsTime;
DWORD dwFormatFlags;
- LPCTSTR lpFormat;
+ LPCWSTR lpFormat;
} ClockWndFormats [] = {
- { TRUE, 0, NULL },
- { FALSE, 0, TEXT("dddd") },
- { FALSE, DATE_SHORTDATE, NULL }
+ { TRUE, 0, NULL },
+ { FALSE, 0, L"dddd" },
+ { FALSE, DATE_SHORTDATE, NULL }
};
-#define CLOCKWND_FORMAT_COUNT (sizeof(ClockWndFormats) / sizeof(ClockWndFormats[0]))
+#define CLOCKWND_FORMAT_COUNT (_ARRAYSIZE(ClockWndFormats))
#define TRAY_CLOCK_WND_SPACING_X 0
#define TRAY_CLOCK_WND_SPACING_Y 0
ZeroMemory(&LocalTime, sizeof(LocalTime));
ZeroMemory(&CurrentSize, sizeof(CurrentSize));
ZeroMemory(LineSizes, sizeof(LineSizes));
- ZeroMemory(szLines, sizeof(LineSizes));
+ ZeroMemory(szLines, sizeof(szLines));
}
virtual ~CTrayClockWnd() { }
0,
TMT_TEXTCOLOR,
&textColor);
+
+ if (this->hFont != NULL)
+ DeleteObject(this->hFont);
+
+ SetFont(hFont, FALSE);
}
else
{
- NONCLIENTMETRICS ncm = { 0 };
- ncm.cbSize = sizeof(ncm);
- SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, FALSE);
-
- hFont = CreateFontIndirectW(&ncm.lfMessageFont);
-
+ /* We don't need to set a font here, our parent will use
+ * WM_SETFONT to set the right one when themes are not enabled. */
textColor = RGB(0, 0, 0);
}
- SetFont(hFont, FALSE);
-
CloseThemeData(clockTheme);
return TRUE;
{
HDC hDC;
HFONT hPrevFont;
- INT c, i;
+ UINT c, i;
BOOL bRet = TRUE;
- hDC = GetDC(m_hWnd);
+ hDC = GetDC();
if (hDC != NULL)
{
if (hFont)
hPrevFont = (HFONT) SelectObject(hDC, hFont);
- for (i = 0; i != CLOCKWND_FORMAT_COUNT && bRet; i++)
+ for (i = 0; i < CLOCKWND_FORMAT_COUNT && bRet; i++)
{
- if (szLines[i][0] != TEXT('\0') &&
- !GetTextExtentPoint(hDC, szLines[i], _tcslen(szLines[i]),
- &LineSizes[i]))
+ if (szLines[i][0] != L'\0' &&
+ !GetTextExtentPointW(hDC, szLines[i], wcslen(szLines[i]),
+ &LineSizes[i]))
{
bRet = FALSE;
break;
if (hFont)
SelectObject(hDC, hPrevFont);
- ReleaseDC(m_hWnd, hDC);
+ ReleaseDC(hDC);
if (bRet)
{
LineSpacing = 0;
/* calculate the line spacing */
- for (i = 0, c = 0; i != CLOCKWND_FORMAT_COUNT; i++)
+ for (i = 0, c = 0; i < CLOCKWND_FORMAT_COUNT; i++)
{
if (LineSizes[i].cx > 0)
{
if (c > 0)
{
- /* We want a spaceing of 1/2 line */
+ /* We want a spacing of 1/2 line */
LineSpacing = (LineSpacing / c) / 2;
}
WORD GetMinimumSize(IN BOOL Horizontal, IN OUT PSIZE pSize)
{
WORD iLinesVisible = 0;
- INT i;
+ UINT i;
SIZE szMax = { 0, 0 };
if (!LinesMeasured)
if (!LinesMeasured)
return 0;
- for (i = 0;
- i != CLOCKWND_FORMAT_COUNT;
- i++)
+ for (i = 0; i < CLOCKWND_FORMAT_COUNT; i++)
{
if (LineSizes[i].cx != 0)
{
}
- VOID UpdateWnd()
+ VOID UpdateWnd()
{
SIZE szPrevCurrent;
- INT BufSize, iRet, i;
+ UINT BufSize, i;
+ INT iRet;
RECT rcClient;
- ZeroMemory(LineSizes,
- sizeof(LineSizes));
+ ZeroMemory(LineSizes, sizeof(LineSizes));
szPrevCurrent = CurrentSize;
- for (i = 0;
- i != CLOCKWND_FORMAT_COUNT;
- i++)
+ for (i = 0; i < CLOCKWND_FORMAT_COUNT; i++)
{
- szLines[i][0] = TEXT('\0');
- BufSize = sizeof(szLines[0]) / sizeof(szLines[0][0]);
+ szLines[i][0] = L'\0';
+ BufSize = _countof(szLines[0]);
if (ClockWndFormats[i].IsTime)
{
iRet = GetTimeFormat(LOCALE_USER_DEFAULT,
- AdvancedSettings.bShowSeconds ? ClockWndFormats[i].dwFormatFlags : TIME_NOSECONDS,
+ TaskBarSettings.bShowSeconds ? ClockWndFormats[i].dwFormatFlags : TIME_NOSECONDS,
&LocalTime,
ClockWndFormats[i].lpFormat,
szLines[i],
CurrentSize = szWnd;
}
- if (IsWindowVisible(m_hWnd))
+ if (IsWindowVisible())
{
InvalidateRect(NULL, TRUE);
NMHDR nmh;
nmh.hwndFrom = m_hWnd;
- nmh.idFrom = GetWindowLongPtr(m_hWnd, GWLP_ID);
+ nmh.idFrom = GetWindowLongPtr(GWLP_ID);
nmh.code = NTNWM_REALIGN;
SendMessage(hWndNotify,
}
}
- VOID Update()
+ VOID Update()
{
GetLocalTime(&LocalTime);
UpdateWnd();
}
- UINT CalculateDueTime()
+ UINT CalculateDueTime()
{
UINT uiDueTime;
/* Calculate the due time */
GetLocalTime(&LocalTime);
uiDueTime = 1000 - (UINT) LocalTime.wMilliseconds;
- if (AdvancedSettings.bShowSeconds)
+ if (TaskBarSettings.bShowSeconds)
uiDueTime += (UINT) LocalTime.wSecond * 100;
else
uiDueTime += (59 - (UINT) LocalTime.wSecond) * 1000;
return uiDueTime;
}
- BOOL ResetTime()
+ BOOL ResetTime()
{
UINT uiDueTime;
BOOL Ret;
return Ret;
}
- VOID CalibrateTimer()
+ VOID CalibrateTimer()
{
UINT uiDueTime;
BOOL Ret;
uiDueTime = CalculateDueTime();
- if (AdvancedSettings.bShowSeconds)
+ if (TaskBarSettings.bShowSeconds)
{
uiWait1 = 1000 - 200;
uiWait2 = 1000;
{
RECT rcClient;
HFONT hPrevFont;
- int iPrevBkMode, i, line;
+ INT iPrevBkMode;
+ UINT i, line;
PAINTSTRUCT ps;
HDC hDC = (HDC) wParam;
rcClient.bottom = rcClient.top + CurrentSize.cy;
for (i = 0, line = 0;
- i != CLOCKWND_FORMAT_COUNT && line < VisibleLines;
- i++)
+ i < CLOCKWND_FORMAT_COUNT && line < VisibleLines;
+ i++)
{
if (LineSizes[i].cx != 0)
{
TRAY_CLOCK_WND_SPACING_X,
rcClient.top + TRAY_CLOCK_WND_SPACING_Y,
szLines[i],
- _tcslen(szLines[i]));
+ wcslen(szLines[i]));
rcClient.top += LineSizes[i].cy + LineSpacing;
line++;
MESSAGE_HANDLER(WM_SIZE, OnSize)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
+ MESSAGE_HANDLER(WM_THEMECHANGED, OnThemeChanged)
MESSAGE_HANDLER(WM_TIMER, OnTimer)
MESSAGE_HANDLER(WM_NCHITTEST, OnNcHitTest)
+ MESSAGE_HANDLER(WM_SETFONT, OnSetFont)
MESSAGE_HANDLER(TCWM_GETMINIMUMSIZE, OnGetMinimumSize)
MESSAGE_HANDLER(TCWM_UPDATETIME, OnUpdateTime)
Create(hWndParent, 0, NULL, dwStyle);
if (m_hWnd != NULL)
- {
SetWindowTheme(m_hWnd, L"TrayNotify", NULL);
- OnThemeChanged();
- }
return m_hWnd;
m_pager = new CSysPagerWnd();
m_pager->_Init(m_hWnd, !HideClock);
- OnThemeChanged();
-
return TRUE;
}
- BOOL GetMinimumSize(IN BOOL Horizontal, IN OUT PSIZE pSize)
+ BOOL GetMinimumSize(IN OUT PSIZE pSize)
{
SIZE szClock = { 0, 0 };
SIZE szTray = { 0, 0 };
- IsHorizontal = Horizontal;
- if (IsHorizontal)
- SetWindowTheme(m_hWnd, L"TrayNotifyHoriz", NULL);
- else
- SetWindowTheme(m_hWnd, L"TrayNotifyVert", NULL);
-
if (!HideClock)
{
- if (Horizontal)
+ if (IsHorizontal)
{
szClock.cy = pSize->cy - 2 * TRAY_NOTIFY_WND_SPACING_Y;
if (szClock.cy <= 0)
goto NoClock;
}
- m_clock->SendMessage(TCWM_GETMINIMUMSIZE, (WPARAM) Horizontal, (LPARAM) &szClock);
+ m_clock->SendMessage(TCWM_GETMINIMUMSIZE, (WPARAM) IsHorizontal, (LPARAM) &szClock);
szTrayClockMin = szClock;
}
NoClock:
szTrayClockMin = szClock;
- if (Horizontal)
+ if (IsHorizontal)
{
szTray.cy = pSize->cy - 2 * TRAY_NOTIFY_WND_SPACING_Y;
}
szTray.cx = pSize->cx - 2 * TRAY_NOTIFY_WND_SPACING_X;
}
- m_pager->GetSize(Horizontal, &szTray);
+ m_pager->GetSize(IsHorizontal, &szTray);
szTrayNotify = szTray;
- if (Horizontal)
+ if (IsHorizontal)
{
pSize->cx = 2 * TRAY_NOTIFY_WND_SPACING_X;
LRESULT DrawBackground(HDC hdc)
{
+ HRESULT res;
RECT rect;
GetClientRect(&rect);
DrawThemeParentBackground(m_hWnd, hdc, &rect);
}
- DrawThemeBackground(TrayTheme, hdc, TNP_BACKGROUND, 0, &rect, 0);
+ res = DrawThemeBackground(TrayTheme, hdc, TNP_BACKGROUND, 0, &rect, 0);
}
- return TRUE;
+ return res;
}
LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
return DrawBackground(hdc);
}
- LRESULT NotifyMsg(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
+ BOOL NotifyIconCmd(WPARAM wParam, LPARAM lParam)
{
if (m_pager)
{
- return m_pager->NotifyMsg(uMsg, wParam, lParam, bHandled);
+ return m_pager->NotifyIconCmd(wParam, lParam);
}
return TRUE;
BOOL GetClockRect(OUT PRECT rcClock)
{
- if (!IsWindowVisible(m_clock->m_hWnd))
+ if (!m_clock->IsWindowVisible())
return FALSE;
- return GetWindowRect(m_clock->m_hWnd, rcClock);
+ return m_clock->GetWindowRect(rcClock);
}
LRESULT OnGetMinimumSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
- return (LRESULT) GetMinimumSize((BOOL) wParam, (PSIZE) lParam);
+ BOOL Horizontal = (BOOL) wParam;
+
+ if (Horizontal != IsHorizontal)
+ {
+ IsHorizontal = Horizontal;
+ if (IsHorizontal)
+ SetWindowTheme(m_hWnd, L"TrayNotifyHoriz", NULL);
+ else
+ SetWindowTheme(m_hWnd, L"TrayNotifyVert", NULL);
+ }
+
+ return (LRESULT) GetMinimumSize((PSIZE) lParam);
}
LRESULT OnUpdateTime(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
}
BOOL
-TrayNotify_NotifyMsg(CTrayNotifyWnd* pTrayNotify, WPARAM wParam, LPARAM lParam)
+TrayNotify_NotifyIconCmd(CTrayNotifyWnd* pTrayNotify, WPARAM wParam, LPARAM lParam)
{
- BOOL bDummy;
- return pTrayNotify->NotifyMsg(0, wParam, lParam, bDummy);
+ return pTrayNotify->NotifyIconCmd(wParam, lParam);
}
BOOL