4 * Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
5 * Copyright 2018 Ged Murphy <gedmurphy@reactos.org>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28 static const WCHAR szTrayNotifyWndClass
[] = TEXT("TrayNotifyWnd");
30 #define TRAY_NOTIFY_WND_SPACING_X 1
31 #define TRAY_NOTIFY_WND_SPACING_Y 1
33 class CTrayNotifyWnd
:
34 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
35 public CWindowImpl
< CTrayNotifyWnd
, CWindow
, CControlWinTraits
>
39 CSysPagerWnd
* m_pager
;
40 CTrayClockWnd
* m_clock
;
42 CComPtr
<ITrayWindow
> TrayWindow
;
47 MARGINS ContentMargin
;
58 ZeroMemory(&szTrayClockMin
, sizeof(szTrayClockMin
));
59 ZeroMemory(&szTrayNotify
, sizeof(szTrayNotify
));
60 ZeroMemory(&ContentMargin
, sizeof(ContentMargin
));
62 virtual ~CTrayNotifyWnd() { }
64 LRESULT
OnThemeChanged()
67 CloseThemeData(TrayTheme
);
70 TrayTheme
= OpenThemeData(m_hWnd
, L
"TrayNotify");
76 SetWindowExStyle(m_hWnd
, WS_EX_STATICEDGE
, 0);
78 GetThemeMargins(TrayTheme
,
88 SetWindowExStyle(m_hWnd
, WS_EX_STATICEDGE
, WS_EX_STATICEDGE
);
90 ContentMargin
.cxLeftWidth
= 2;
91 ContentMargin
.cxRightWidth
= 2;
92 ContentMargin
.cyTopHeight
= 2;
93 ContentMargin
.cyBottomHeight
= 2;
99 LRESULT
OnThemeChanged(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
101 return OnThemeChanged();
104 LRESULT
OnCreate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
106 m_clock
= new CTrayClockWnd();
107 m_clock
->_Init(m_hWnd
, !g_TaskbarSettings
.sr
.HideClock
);
109 m_pager
= new CSysPagerWnd();
110 m_pager
->_Init(m_hWnd
, !g_TaskbarSettings
.sr
.HideClock
);
115 BOOL
GetMinimumSize(IN OUT PSIZE pSize
)
117 SIZE szClock
= { 0, 0 };
118 SIZE szTray
= { 0, 0 };
120 if (!g_TaskbarSettings
.sr
.HideClock
)
124 szClock
.cy
= pSize
->cy
- 2 * TRAY_NOTIFY_WND_SPACING_Y
;
130 szClock
.cx
= pSize
->cx
- 2 * TRAY_NOTIFY_WND_SPACING_X
;
135 m_clock
->SendMessage(TCWM_GETMINIMUMSIZE
, (WPARAM
) IsHorizontal
, (LPARAM
) &szClock
);
137 szTrayClockMin
= szClock
;
141 szTrayClockMin
= szClock
;
145 szTray
.cy
= pSize
->cy
- 2 * TRAY_NOTIFY_WND_SPACING_Y
;
149 szTray
.cx
= pSize
->cx
- 2 * TRAY_NOTIFY_WND_SPACING_X
;
152 m_pager
->GetSize(IsHorizontal
, &szTray
);
154 szTrayNotify
= szTray
;
158 pSize
->cx
= 2 * TRAY_NOTIFY_WND_SPACING_X
;
160 if (!g_TaskbarSettings
.sr
.HideClock
)
161 pSize
->cx
+= TRAY_NOTIFY_WND_SPACING_X
+ szTrayClockMin
.cx
;
163 pSize
->cx
+= szTray
.cx
;
167 pSize
->cy
= 2 * TRAY_NOTIFY_WND_SPACING_Y
;
169 if (!g_TaskbarSettings
.sr
.HideClock
)
170 pSize
->cy
+= TRAY_NOTIFY_WND_SPACING_Y
+ szTrayClockMin
.cy
;
172 pSize
->cy
+= szTray
.cy
;
175 pSize
->cy
+= ContentMargin
.cyTopHeight
+ ContentMargin
.cyBottomHeight
;
176 pSize
->cx
+= ContentMargin
.cxLeftWidth
+ ContentMargin
.cxRightWidth
;
181 VOID
Size(IN
const SIZE
*pszClient
)
183 if (!g_TaskbarSettings
.sr
.HideClock
)
190 ptClock
.x
= pszClient
->cx
- szTrayClockMin
.cx
- ContentMargin
.cxRightWidth
;
191 ptClock
.y
= ContentMargin
.cyTopHeight
;
192 szClock
.cx
= szTrayClockMin
.cx
;
193 szClock
.cy
= pszClient
->cy
- ContentMargin
.cyTopHeight
- ContentMargin
.cyBottomHeight
;
197 ptClock
.x
= ContentMargin
.cxLeftWidth
;
198 ptClock
.y
= pszClient
->cy
- szTrayClockMin
.cy
;
199 szClock
.cx
= pszClient
->cx
- ContentMargin
.cxLeftWidth
- ContentMargin
.cxRightWidth
;
200 szClock
.cy
= szTrayClockMin
.cy
;
203 m_clock
->SetWindowPos(
215 ptPager
.x
= ContentMargin
.cxLeftWidth
;
216 ptPager
.y
= (pszClient
->cy
- szTrayNotify
.cy
)/2;
220 ptPager
.x
= (pszClient
->cx
- szTrayNotify
.cx
)/2;
221 ptPager
.y
= ContentMargin
.cyTopHeight
;
224 m_pager
->SetWindowPos(
234 LRESULT
DrawBackground(HDC hdc
)
239 GetClientRect(&rect
);
243 if (IsThemeBackgroundPartiallyTransparent(TrayTheme
, TNP_BACKGROUND
, 0))
245 DrawThemeParentBackground(m_hWnd
, hdc
, &rect
);
248 res
= DrawThemeBackground(TrayTheme
, hdc
, TNP_BACKGROUND
, 0, &rect
, 0);
254 LRESULT
OnEraseBackground(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
256 HDC hdc
= (HDC
) wParam
;
264 return DrawBackground(hdc
);
267 BOOL
NotifyIconCmd(WPARAM wParam
, LPARAM lParam
)
271 return m_pager
->NotifyIconCmd(wParam
, lParam
);
277 BOOL
GetClockRect(OUT PRECT rcClock
)
279 if (!m_clock
->IsWindowVisible())
282 return m_clock
->GetWindowRect(rcClock
);
285 LRESULT
OnGetMinimumSize(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
287 BOOL Horizontal
= (BOOL
) wParam
;
289 if (Horizontal
!= IsHorizontal
)
291 IsHorizontal
= Horizontal
;
293 SetWindowTheme(m_hWnd
, L
"TrayNotifyHoriz", NULL
);
295 SetWindowTheme(m_hWnd
, L
"TrayNotifyVert", NULL
);
298 return (LRESULT
) GetMinimumSize((PSIZE
) lParam
);
301 LRESULT
OnUpdateTime(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
305 /* Forward the message to the tray clock window procedure */
306 return m_clock
->OnUpdateTime(uMsg
, wParam
, lParam
, bHandled
);
311 LRESULT
OnSize(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
315 szClient
.cx
= LOWORD(lParam
);
316 szClient
.cy
= HIWORD(lParam
);
323 LRESULT
OnNcHitTest(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
325 return HTTRANSPARENT
;
328 LRESULT
OnShowClock(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
330 BOOL PrevHidden
= g_TaskbarSettings
.sr
.HideClock
;
331 g_TaskbarSettings
.sr
.HideClock
= (wParam
== 0);
333 if (m_clock
!= NULL
&& PrevHidden
!= g_TaskbarSettings
.sr
.HideClock
)
335 m_clock
->ShowWindow(g_TaskbarSettings
.sr
.HideClock
? SW_HIDE
: SW_SHOW
);
338 return (LRESULT
) (!PrevHidden
);
341 LRESULT
OnTaskbarSettingsChanged(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
343 TaskbarSettings
* newSettings
= (TaskbarSettings
*)lParam
;
344 if (newSettings
->bShowSeconds
!= g_TaskbarSettings
.bShowSeconds
)
346 g_TaskbarSettings
.bShowSeconds
= newSettings
->bShowSeconds
;
347 /* TODO: Toggle showing seconds */
350 if (newSettings
->sr
.HideClock
!= g_TaskbarSettings
.sr
.HideClock
)
352 g_TaskbarSettings
.sr
.HideClock
= newSettings
->sr
.HideClock
;
353 /* TODO: Toggle hiding the clock */
359 LRESULT
OnNotify(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
361 const NMHDR
*nmh
= (const NMHDR
*) lParam
;
363 if (nmh
->hwndFrom
== m_clock
->m_hWnd
)
365 /* Pass down notifications */
366 return m_clock
->SendMessage(WM_NOTIFY
, wParam
, lParam
);
372 LRESULT
OnSetFont(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
376 m_clock
->SendMessageW(WM_SETFONT
, wParam
, lParam
);
383 LRESULT
OnCtxMenu(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
389 LRESULT
OnSettingChanged(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
391 if (wParam
== SPI_SETNONCLIENTMETRICS
)
393 m_pager
->ResizeImagelist();
398 DECLARE_WND_CLASS_EX(szTrayNotifyWndClass
, CS_DBLCLKS
, COLOR_3DFACE
)
400 BEGIN_MSG_MAP(CTrayNotifyWnd
)
401 MESSAGE_HANDLER(WM_CREATE
, OnCreate
)
402 MESSAGE_HANDLER(WM_THEMECHANGED
, OnThemeChanged
)
403 MESSAGE_HANDLER(WM_ERASEBKGND
, OnEraseBackground
)
404 MESSAGE_HANDLER(WM_SETTINGCHANGE
, OnSettingChanged
)
405 MESSAGE_HANDLER(WM_SIZE
, OnSize
)
406 MESSAGE_HANDLER(WM_NCHITTEST
, OnNcHitTest
)
407 MESSAGE_HANDLER(WM_NOTIFY
, OnNotify
)
408 MESSAGE_HANDLER(WM_SETFONT
, OnSetFont
)
409 MESSAGE_HANDLER(WM_CONTEXTMENU
, OnCtxMenu
) // FIXME: This handler is not necessary in Windows
410 MESSAGE_HANDLER(TNWM_GETMINIMUMSIZE
, OnGetMinimumSize
)
411 MESSAGE_HANDLER(TNWM_UPDATETIME
, OnUpdateTime
)
412 MESSAGE_HANDLER(TNWM_SHOWCLOCK
, OnShowClock
)
413 MESSAGE_HANDLER(TWM_SETTINGSCHANGED
, OnTaskbarSettingsChanged
)
416 HWND
_Init(IN OUT ITrayWindow
*TrayWindow
)
420 hWndTrayWindow
= TrayWindow
->GetHWND();
421 if (hWndTrayWindow
== NULL
)
424 this->TrayWindow
= TrayWindow
;
425 this->hWndNotify
= hWndTrayWindow
;
427 DWORD dwStyle
= WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
;
428 return Create(hWndTrayWindow
, 0, NULL
, dwStyle
, WS_EX_STATICEDGE
);
432 HWND
CreateTrayNotifyWnd(IN OUT ITrayWindow
*Tray
, CTrayNotifyWnd
** ppinstance
)
434 CTrayNotifyWnd
* pTrayNotify
= new CTrayNotifyWnd();
435 // TODO: Destroy after the window is destroyed
436 *ppinstance
= pTrayNotify
;
438 return pTrayNotify
->_Init(Tray
);
442 TrayNotify_NotifyIconCmd(CTrayNotifyWnd
* pTrayNotify
, WPARAM wParam
, LPARAM lParam
)
444 return pTrayNotify
->NotifyIconCmd(wParam
, lParam
);
448 TrayNotify_GetClockRect(CTrayNotifyWnd
* pTrayNotify
, OUT PRECT rcClock
)
450 return pTrayNotify
->GetClockRect(rcClock
);