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 CComCoClass
<CTrayNotifyWnd
>,
35 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
36 public CWindowImpl
< CTrayNotifyWnd
, CWindow
, CControlWinTraits
>,
39 CComPtr
<IUnknown
> m_clock
;
40 CComPtr
<IUnknown
> m_pager
;
48 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
)
108 hr
= CTrayClockWnd_CreateInstance(m_hWnd
, IID_PPV_ARG(IUnknown
, &m_clock
));
109 if (FAILED_UNEXPECTEDLY(hr
))
112 hr
= IUnknown_GetWindow(m_clock
, &m_hwndClock
);
113 if (FAILED_UNEXPECTEDLY(hr
))
116 hr
= CSysPagerWnd_CreateInstance(m_hWnd
, IID_PPV_ARG(IUnknown
, &m_pager
));
117 if (FAILED_UNEXPECTEDLY(hr
))
120 hr
= IUnknown_GetWindow(m_pager
, &m_hwndPager
);
121 if (FAILED_UNEXPECTEDLY(hr
))
127 BOOL
GetMinimumSize(IN OUT PSIZE pSize
)
129 SIZE szClock
= { 0, 0 };
130 SIZE szTray
= { 0, 0 };
132 if (!g_TaskbarSettings
.sr
.HideClock
)
136 szClock
.cy
= pSize
->cy
- 2 * TRAY_NOTIFY_WND_SPACING_Y
;
142 szClock
.cx
= pSize
->cx
- 2 * TRAY_NOTIFY_WND_SPACING_X
;
147 ::SendMessage(m_hwndClock
, TNWM_GETMINIMUMSIZE
, (WPARAM
) IsHorizontal
, (LPARAM
) &szClock
);
149 szTrayClockMin
= szClock
;
153 szTrayClockMin
= szClock
;
157 szTray
.cy
= pSize
->cy
- 2 * TRAY_NOTIFY_WND_SPACING_Y
;
161 szTray
.cx
= pSize
->cx
- 2 * TRAY_NOTIFY_WND_SPACING_X
;
164 ::SendMessage(m_hwndPager
, TNWM_GETMINIMUMSIZE
, (WPARAM
) IsHorizontal
, (LPARAM
) &szTray
);
166 szTrayNotify
= szTray
;
170 pSize
->cx
= 2 * TRAY_NOTIFY_WND_SPACING_X
;
172 if (!g_TaskbarSettings
.sr
.HideClock
)
173 pSize
->cx
+= TRAY_NOTIFY_WND_SPACING_X
+ szTrayClockMin
.cx
;
175 pSize
->cx
+= szTray
.cx
;
176 pSize
->cx
+= ContentMargin
.cxLeftWidth
+ ContentMargin
.cxRightWidth
;
180 pSize
->cy
= 2 * TRAY_NOTIFY_WND_SPACING_Y
;
182 if (!g_TaskbarSettings
.sr
.HideClock
)
183 pSize
->cy
+= TRAY_NOTIFY_WND_SPACING_Y
+ szTrayClockMin
.cy
;
185 pSize
->cy
+= szTray
.cy
;
186 pSize
->cy
+= ContentMargin
.cyTopHeight
+ ContentMargin
.cyBottomHeight
;
192 VOID
Size(IN
const SIZE
*pszClient
)
194 if (!g_TaskbarSettings
.sr
.HideClock
)
201 ptClock
.x
= pszClient
->cx
- szTrayClockMin
.cx
- ContentMargin
.cxRightWidth
;
202 ptClock
.y
= ContentMargin
.cyTopHeight
;
203 szClock
.cx
= szTrayClockMin
.cx
;
204 szClock
.cy
= pszClient
->cy
- ContentMargin
.cyTopHeight
- ContentMargin
.cyBottomHeight
;
208 ptClock
.x
= ContentMargin
.cxLeftWidth
;
209 ptClock
.y
= pszClient
->cy
- szTrayClockMin
.cy
;
210 szClock
.cx
= pszClient
->cx
- ContentMargin
.cxLeftWidth
- ContentMargin
.cxRightWidth
;
211 szClock
.cy
= szTrayClockMin
.cy
;
214 ::SetWindowPos(m_hwndClock
,
226 ptPager
.x
= ContentMargin
.cxLeftWidth
;
227 ptPager
.y
= (pszClient
->cy
- szTrayNotify
.cy
)/2;
231 ptPager
.x
= (pszClient
->cx
- szTrayNotify
.cx
)/2;
232 ptPager
.y
= ContentMargin
.cyTopHeight
;
235 ::SetWindowPos(m_hwndPager
,
245 LRESULT
OnEraseBackground(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
247 HDC hdc
= (HDC
) wParam
;
256 GetClientRect(&rect
);
257 if (IsThemeBackgroundPartiallyTransparent(TrayTheme
, TNP_BACKGROUND
, 0))
258 DrawThemeParentBackground(m_hWnd
, hdc
, &rect
);
260 DrawThemeBackground(TrayTheme
, hdc
, TNP_BACKGROUND
, 0, &rect
, 0);
265 LRESULT
OnGetMinimumSize(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
267 BOOL Horizontal
= (BOOL
) wParam
;
269 if (Horizontal
!= IsHorizontal
)
271 IsHorizontal
= Horizontal
;
273 SetWindowTheme(m_hWnd
, L
"TrayNotifyHoriz", NULL
);
275 SetWindowTheme(m_hWnd
, L
"TrayNotifyVert", NULL
);
278 return (LRESULT
) GetMinimumSize((PSIZE
) lParam
);
281 LRESULT
OnSize(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
285 szClient
.cx
= LOWORD(lParam
);
286 szClient
.cy
= HIWORD(lParam
);
293 LRESULT
OnNcHitTest(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
295 return HTTRANSPARENT
;
298 LRESULT
OnCtxMenu(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
304 LRESULT
OnClockMessage(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
306 return SendMessageW(m_hwndClock
, uMsg
, wParam
, lParam
);
309 LRESULT
OnPagerMessage(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
311 return SendMessageW(m_hwndPager
, uMsg
, wParam
, lParam
);
314 LRESULT
OnRealign(INT uCode
, LPNMHDR hdr
, BOOL
& bHandled
)
316 hdr
->hwndFrom
= m_hWnd
;
317 return GetParent().SendMessage(WM_NOTIFY
, 0, (LPARAM
)hdr
);
320 HRESULT WINAPI
GetWindow(HWND
* phwnd
)
328 HRESULT WINAPI
ContextSensitiveHelp(BOOL fEnterMode
)
333 DECLARE_NOT_AGGREGATABLE(CTrayNotifyWnd
)
335 DECLARE_PROTECT_FINAL_CONSTRUCT()
336 BEGIN_COM_MAP(CTrayNotifyWnd
)
337 COM_INTERFACE_ENTRY_IID(IID_IOleWindow
, IOleWindow
)
340 DECLARE_WND_CLASS_EX(szTrayNotifyWndClass
, CS_DBLCLKS
, COLOR_3DFACE
)
342 BEGIN_MSG_MAP(CTrayNotifyWnd
)
343 MESSAGE_HANDLER(WM_CREATE
, OnCreate
)
344 MESSAGE_HANDLER(WM_THEMECHANGED
, OnThemeChanged
)
345 MESSAGE_HANDLER(WM_ERASEBKGND
, OnEraseBackground
)
346 MESSAGE_HANDLER(WM_SIZE
, OnSize
)
347 MESSAGE_HANDLER(WM_NCHITTEST
, OnNcHitTest
)
348 MESSAGE_HANDLER(WM_CONTEXTMENU
, OnCtxMenu
) // FIXME: This handler is not necessary in Windows
349 MESSAGE_HANDLER(WM_NCLBUTTONDBLCLK
, OnClockMessage
)
350 MESSAGE_HANDLER(TWM_SETTINGSCHANGED
, OnClockMessage
)
351 MESSAGE_HANDLER(WM_SETFONT
, OnClockMessage
)
352 MESSAGE_HANDLER(WM_SETTINGCHANGE
, OnPagerMessage
)
353 MESSAGE_HANDLER(WM_COPYDATA
, OnPagerMessage
)
354 NOTIFY_CODE_HANDLER(NTNWM_REALIGN
, OnRealign
)
355 MESSAGE_HANDLER(TNWM_GETMINIMUMSIZE
, OnGetMinimumSize
)
358 HRESULT
Initialize(IN HWND hwndParent
)
360 DWORD dwStyle
= WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
;
361 Create(hwndParent
, 0, NULL
, dwStyle
, WS_EX_STATICEDGE
);
368 HRESULT
CTrayNotifyWnd_CreateInstance(HWND hwndParent
, REFIID riid
, void **ppv
)
370 return ShellObjectCreatorInit
<CTrayNotifyWnd
>(hwndParent
, riid
, ppv
);