1 /*
2 * ReactOS Explorer
3 *
4 * Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
5 * Copyright 2018 Ged Murphy <gedmurphy@reactos.org>
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #include "precomp.h"
23
24 /*
25 * TrayClockWnd
26 */
27
28 const struct
29 {
30 BOOL IsTime;
31 DWORD dwFormatFlags;
32 LPCWSTR lpFormat;
33 } ClockWndFormats[] = {
34 { TRUE, 0, NULL },
35 { FALSE, 0, L"dddd" },
36 { FALSE, DATE_SHORTDATE, NULL }
37 };
38 const UINT ClockWndFormatsCount = _ARRAYSIZE(ClockWndFormats);
39
40 #define CLOCKWND_FORMAT_COUNT ClockWndFormatsCount
41 #define CLOCKWND_FORMAT_TIME 0
42 #define CLOCKWND_FORMAT_DAY 1
43 #define CLOCKWND_FORMAT_DATE 2
44
45 static const WCHAR szTrayClockWndClass[] = L"TrayClockWClass";
46
47 class CTrayClockWnd :
48 public CComCoClass<CTrayClockWnd>,
49 public CComObjectRootEx<CComMultiThreadModelNoCS>,
50 public CWindowImpl < CTrayClockWnd, CWindow, CControlWinTraits >,
51 public IOleWindow
52 {
53 HFONT hFont;
54 COLORREF textColor;
55 RECT rcText;
56 SYSTEMTIME LocalTime;
57 CTooltips m_tooltip;
58
59 union
60 {
61 DWORD dwFlags;
62 struct
63 {
64 DWORD IsTimerEnabled : 1;
65 DWORD IsInitTimerEnabled : 1;
66 DWORD LinesMeasured : 1;
67 DWORD IsHorizontal : 1;
68 };
69 };
70 DWORD LineSpacing;
71 SIZE CurrentSize;
72 WORD VisibleLines;
73 SIZE LineSizes[CLOCKWND_FORMAT_COUNT];
74 WCHAR szLines[CLOCKWND_FORMAT_COUNT][48];
75
76 public:
77 CTrayClockWnd();
78 virtual ~CTrayClockWnd();
79
80 private:
81 LRESULT OnThemeChanged();
82 LRESULT OnThemeChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
83
84 BOOL MeasureLines();
85 WORD GetMinimumSize(IN BOOL Horizontal, IN OUT PSIZE pSize);
86 VOID UpdateWnd();
87 VOID Update();
88 UINT CalculateDueTime();
89 BOOL ResetTime();
90 VOID CalibrateTimer();
91 LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
92 LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
93 VOID SetFont(IN HFONT hNewFont, IN BOOL bRedraw);
94 LRESULT DrawBackground(HDC hdc);
95 LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
96 LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
97 LRESULT OnGetMinimumSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
98 LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
99 LRESULT OnSetFont(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
100 LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
101 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
102 LRESULT OnTaskbarSettingsChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
103 LRESULT OnLButtonDblClick(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
104 VOID PaintLine(IN HDC hDC, IN OUT RECT *rcClient, IN UINT LineNumber, IN UINT szLinesIndex);
105
106 public:
107 // *** IOleWindow methods ***
108
109 STDMETHODIMP
GetWindow(HWND * phwnd)110 GetWindow(HWND* phwnd) override
111 {
112 if (!phwnd)
113 return E_INVALIDARG;
114 *phwnd = m_hWnd;
115 return S_OK;
116 }
117
118 STDMETHODIMP
ContextSensitiveHelp(BOOL fEnterMode)119 ContextSensitiveHelp(BOOL fEnterMode) override
120 {
121 return E_NOTIMPL;
122 }
123
124 DECLARE_NOT_AGGREGATABLE(CTrayClockWnd)
125
126 DECLARE_PROTECT_FINAL_CONSTRUCT()
127 BEGIN_COM_MAP(CTrayClockWnd)
128 COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
129 END_COM_MAP()
130
131 DECLARE_WND_CLASS_EX(szTrayClockWndClass, CS_DBLCLKS, COLOR_3DFACE)
132
133 BEGIN_MSG_MAP(CTrayClockWnd)
134 MESSAGE_HANDLER(WM_CREATE, OnCreate)
135 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
136 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
137 MESSAGE_HANDLER(WM_SIZE, OnSize)
138 MESSAGE_HANDLER(WM_PAINT, OnPaint)
139 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
140 MESSAGE_HANDLER(WM_THEMECHANGED, OnThemeChanged)
141 MESSAGE_HANDLER(WM_TIMER, OnTimer)
142 MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu)
143 MESSAGE_HANDLER(WM_SETFONT, OnSetFont)
144 MESSAGE_HANDLER(TNWM_GETMINIMUMSIZE, OnGetMinimumSize)
145 MESSAGE_HANDLER(TWM_SETTINGSCHANGED, OnTaskbarSettingsChanged)
146 MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDblClick)
147 END_MSG_MAP()
148
149 HRESULT Initialize(IN HWND hWndParent);
150 };
151
152 #define ID_TRAYCLOCK_TIMER 0
153 #define ID_TRAYCLOCK_TIMER_INIT 1
154
155 #define TRAY_CLOCK_WND_SPACING_X 5
156 #define TRAY_CLOCK_WND_SPACING_Y 0
157
CTrayClockWnd()158 CTrayClockWnd::CTrayClockWnd() :
159 hFont(NULL),
160 textColor(0),
161 dwFlags(0),
162 LineSpacing(0),
163 VisibleLines(0)
164 {
165 ZeroMemory(&rcText, sizeof(rcText));
166 ZeroMemory(&LocalTime, sizeof(LocalTime));
167 ZeroMemory(&CurrentSize, sizeof(CurrentSize));
168 ZeroMemory(LineSizes, sizeof(LineSizes));
169 ZeroMemory(szLines, sizeof(szLines));
170 }
~CTrayClockWnd()171 CTrayClockWnd::~CTrayClockWnd() { }
172
OnThemeChanged()173 LRESULT CTrayClockWnd::OnThemeChanged()
174 {
175 LOGFONTW clockFont;
176 HTHEME clockTheme;
177 HFONT hFont;
178
179 clockTheme = OpenThemeData(m_hWnd, L"Clock");
180
181 if (clockTheme)
182 {
183 GetThemeFont(clockTheme, NULL, CLP_TIME, 0, TMT_FONT, &clockFont);
184
185 hFont = CreateFontIndirectW(&clockFont);
186
187 GetThemeColor(clockTheme, CLP_TIME, 0, TMT_TEXTCOLOR, &textColor);
188
189 if (this->hFont != NULL)
190 DeleteObject(this->hFont);
191
192 SetFont(hFont, FALSE);
193
194 CloseThemeData(clockTheme);
195 }
196
197 return TRUE;
198 }
199
OnThemeChanged(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)200 LRESULT CTrayClockWnd::OnThemeChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
201 {
202 return OnThemeChanged();
203 }
204
MeasureLines()205 BOOL CTrayClockWnd::MeasureLines()
206 {
207 HDC hDC;
208 HFONT hPrevFont;
209 UINT c, i;
210 BOOL bRet = TRUE;
211
212 hDC = GetDC();
213 if (hDC != NULL)
214 {
215 if (hFont)
216 hPrevFont = (HFONT) SelectObject(hDC, hFont);
217
218 for (i = 0; i < CLOCKWND_FORMAT_COUNT && bRet; i++)
219 {
220 if (szLines[i][0] != L'\0' &&
221 !GetTextExtentPointW(hDC, szLines[i], wcslen(szLines[i]),
222 &LineSizes[i]))
223 {
224 bRet = FALSE;
225 break;
226 }
227 }
228
229 if (hFont)
230 SelectObject(hDC, hPrevFont);
231
232 ReleaseDC(hDC);
233
234 if (bRet)
235 {
236 LineSpacing = 0;
237
238 /* calculate the line spacing */
239 for (i = 0, c = 0; i < CLOCKWND_FORMAT_COUNT; i++)
240 {
241 if (LineSizes[i].cx > 0)
242 {
243 LineSpacing += LineSizes[i].cy;
244 c++;
245 }
246 }
247
248 if (c > 0)
249 {
250 /* We want a spacing of 1/2 line */
251 LineSpacing = (LineSpacing / c) / 2;
252 }
253
254 return TRUE;
255 }
256 }
257
258 return FALSE;
259 }
260
GetMinimumSize(IN BOOL Horizontal,IN OUT PSIZE pSize)261 WORD CTrayClockWnd::GetMinimumSize(IN BOOL Horizontal, IN OUT PSIZE pSize)
262 {
263 WORD iLinesVisible = 0;
264 UINT i;
265 SIZE szMax = { 0, 0 };
266
267 if (!LinesMeasured)
268 LinesMeasured = MeasureLines();
269
270 if (!LinesMeasured)
271 return 0;
272
273 /* Prevents the date from being cut off when the day of the week is shorter than the date. */
274 if (VisibleLines > 1 && g_TaskbarSettings.bPreferDate)
275 szMax.cx = LineSizes[CLOCKWND_FORMAT_DATE].cx;
276
277 for (i = 0; i < CLOCKWND_FORMAT_COUNT; i++)
278 {
279 if (LineSizes[i].cx != 0)
280 {
281 if (iLinesVisible > 0)
282 {
283 if (Horizontal)
284 {
285 if (szMax.cy + LineSizes[i].cy + (LONG) LineSpacing >
286 pSize->cy - (2 * TRAY_CLOCK_WND_SPACING_Y))
287 {
288 break;
289 }
290 }
291 else
292 {
293 if (LineSizes[i].cx > pSize->cx - (2 * TRAY_CLOCK_WND_SPACING_X))
294 break;
295 }
296
297 /* Add line spacing */
298 szMax.cy += LineSpacing;
299 }
300
301 iLinesVisible++;
302
303 /* Increase maximum rectangle */
304 szMax.cy += LineSizes[i].cy;
305 if (LineSizes[i].cx > szMax.cx)
306 szMax.cx = LineSizes[i].cx;
307 }
308 }
309
310 szMax.cx += 2 * TRAY_CLOCK_WND_SPACING_X;
311 szMax.cy += 2 * TRAY_CLOCK_WND_SPACING_Y;
312
313 *pSize = szMax;
314
315 return iLinesVisible;
316 }
317
UpdateWnd()318 VOID CTrayClockWnd::UpdateWnd()
319 {
320 SIZE szPrevCurrent;
321 UINT BufSize, i;
322 INT iRet;
323 RECT rcClient;
324
325 ZeroMemory(LineSizes, sizeof(LineSizes));
326
327 szPrevCurrent = CurrentSize;
328
329 for (i = 0; i < CLOCKWND_FORMAT_COUNT; i++)
330 {
331 szLines[i][0] = L'\0';
332 BufSize = _countof(szLines[0]);
333
334 if (ClockWndFormats[i].IsTime)
335 {
336 iRet = GetTimeFormat(LOCALE_USER_DEFAULT,
337 g_TaskbarSettings.bShowSeconds ? ClockWndFormats[i].dwFormatFlags : TIME_NOSECONDS,
338 &LocalTime,
339 ClockWndFormats[i].lpFormat,
340 szLines[i],
341 BufSize);
342 }
343 else
344 {
345 iRet = GetDateFormat(LOCALE_USER_DEFAULT,
346 ClockWndFormats[i].dwFormatFlags,
347 &LocalTime,
348 ClockWndFormats[i].lpFormat,
349 szLines[i],
350 BufSize);
351 }
352
353 if (iRet != 0 && i == 0)
354 {
355 /* Set the window text to the time only */
356 SetWindowText(szLines[i]);
357 }
358 }
359
360 LinesMeasured = MeasureLines();
361
362 if (LinesMeasured &&
363 GetClientRect(&rcClient))
364 {
365 SIZE szWnd;
366
367 szWnd.cx = rcClient.right;
368 szWnd.cy = rcClient.bottom;
369
370 VisibleLines = GetMinimumSize(IsHorizontal, &szWnd);
371 CurrentSize = szWnd;
372 }
373
374 if (IsWindowVisible())
375 {
376 InvalidateRect(NULL, TRUE);
377
378 if (szPrevCurrent.cx != CurrentSize.cx ||
379 szPrevCurrent.cy != CurrentSize.cy)
380 {
381 /* Ask the parent to resize */
382 NMHDR nmh = {GetParent(), 0, NTNWM_REALIGN};
383 GetParent().SendMessage(WM_NOTIFY, 0, (LPARAM) &nmh);
384 }
385 }
386
387 int iDateLength = GetDateFormat(LOCALE_USER_DEFAULT,
388 DATE_LONGDATE,
389 &LocalTime,
390 NULL,
391 NULL,
392 0);
393 if (iDateLength <= 0)
394 {
395 return;
396 }
397
398 WCHAR* szDate = new WCHAR[iDateLength];
399 if (GetDateFormat(LOCALE_USER_DEFAULT,
400 DATE_LONGDATE,
401 &LocalTime,
402 NULL,
403 szDate,
404 iDateLength) > 0)
405 {
406 m_tooltip.UpdateTipText(m_hWnd,
407 reinterpret_cast<UINT_PTR>(m_hWnd),
408 szDate);
409 }
410 delete[] szDate;
411 }
412
Update()413 VOID CTrayClockWnd::Update()
414 {
415 GetLocalTime(&LocalTime);
416 UpdateWnd();
417 }
418
CalculateDueTime()419 UINT CTrayClockWnd::CalculateDueTime()
420 {
421 UINT uiDueTime;
422
423 GetLocalTime(&LocalTime);
424 uiDueTime = 1000 - (UINT) LocalTime.wMilliseconds;
425 if (!g_TaskbarSettings.bShowSeconds)
426 uiDueTime += (59 - (UINT) LocalTime.wSecond) * 1000;
427
428 return uiDueTime;
429 }
430
ResetTime()431 BOOL CTrayClockWnd::ResetTime()
432 {
433 UINT uiDueTime;
434 BOOL Ret;
435
436 /* Disable all timers */
437 if (IsTimerEnabled)
438 {
439 KillTimer(ID_TRAYCLOCK_TIMER);
440 IsTimerEnabled = FALSE;
441 }
442 else if (IsInitTimerEnabled)
443 {
444 KillTimer(ID_TRAYCLOCK_TIMER_INIT);
445 }
446
447 uiDueTime = CalculateDueTime();
448
449 /* Set the new timer */
450 Ret = SetTimer(ID_TRAYCLOCK_TIMER_INIT, uiDueTime, NULL) != 0;
451 IsInitTimerEnabled = Ret;
452
453 return Ret;
454 }
455
CalibrateTimer()456 VOID CTrayClockWnd::CalibrateTimer()
457 {
458 UINT uiDueTime;
459 BOOL Ret;
460 UINT uiWait1, uiWait2;
461
462 /* Kill the initialization timer */
463 KillTimer(ID_TRAYCLOCK_TIMER_INIT);
464 IsInitTimerEnabled = FALSE;
465
466 uiDueTime = CalculateDueTime();
467
468 if (g_TaskbarSettings.bShowSeconds)
469 {
470 uiWait1 = 1000 - 200;
471 uiWait2 = 1000;
472 }
473 else
474 {
475 uiWait1 = 60 * 1000 - 200;
476 uiWait2 = 60 * 1000;
477 }
478
479 if (uiDueTime > uiWait1)
480 {
481 /* The update of the clock will be up to 200 ms late, but that's
482 acceptable. We're going to setup a timer that fires depending
483 uiWait2. */
484 Ret = SetTimer(ID_TRAYCLOCK_TIMER, uiWait2, NULL) != 0;
485 IsTimerEnabled = Ret;
486 }
487 else
488 {
489 /* Recalibrate the timer and recalculate again when the current
490 minute/second ends. */
491 ResetTime();
492 }
493
494 /* Update the time */
495 Update();
496 }
497
OnDestroy(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)498 LRESULT CTrayClockWnd::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
499 {
500 /* Disable all timers */
501 if (IsTimerEnabled)
502 {
503 KillTimer(ID_TRAYCLOCK_TIMER);
504 }
505 else if (IsInitTimerEnabled)
506 {
507 KillTimer(ID_TRAYCLOCK_TIMER_INIT);
508 }
509
510 return TRUE;
511 }
512
OnPaint(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)513 LRESULT CTrayClockWnd::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
514 {
515 RECT rcClient;
516 HFONT hPrevFont;
517 INT iPrevBkMode;
518 UINT i, line;
519 PAINTSTRUCT ps;
520 HDC hDC = (HDC) wParam;
521
522 if (wParam == 0)
523 hDC = BeginPaint(&ps);
524
525 if (hDC == NULL)
526 return FALSE;
527
528 if (LinesMeasured &&
529 GetClientRect(&rcClient))
530 {
531 iPrevBkMode = SetBkMode(hDC, TRANSPARENT);
532
533 if (!IsAppThemed())
534 textColor = ::GetSysColor(COLOR_BTNTEXT);
535
536 ::SetTextColor(hDC, textColor);
537
538 hPrevFont = (HFONT) SelectObject(hDC, hFont);
539
540 rcClient.top = (rcClient.bottom - CurrentSize.cy) / 2;
541 rcClient.bottom = rcClient.top + CurrentSize.cy;
542
543 if (VisibleLines == 2)
544 {
545 /* Display either time and weekday (by default), or time and date (opt-in) */
546 PaintLine(hDC, &rcClient, 0, CLOCKWND_FORMAT_TIME);
547 PaintLine(hDC, &rcClient, 1,
548 g_TaskbarSettings.bPreferDate ? CLOCKWND_FORMAT_DATE : CLOCKWND_FORMAT_DAY);
549 }
550 else
551 {
552 for (i = 0, line = 0;
553 i < CLOCKWND_FORMAT_COUNT && line < VisibleLines;
554 i++)
555 {
556 PaintLine(hDC, &rcClient, i, i);
557 line++;
558 }
559 }
560
561 SelectObject(hDC, hPrevFont);
562
563 SetBkMode(hDC, iPrevBkMode);
564 }
565
566 if (wParam == 0)
567 EndPaint(&ps);
568
569 return TRUE;
570 }
571
PaintLine(IN HDC hDC,IN OUT RECT * rcClient,IN UINT LineNumber,IN UINT szLinesIndex)572 VOID CTrayClockWnd::PaintLine(IN HDC hDC, IN OUT RECT *rcClient, IN UINT LineNumber, IN UINT szLinesIndex)
573 {
574 if (LineSizes[LineNumber].cx == 0)
575 return;
576
577 INT HShift = ((IsHorizontal && (VisibleLines <= 1 ||
578 g_TaskbarSettings.UseCompactTrayIcons())) ? 0 : TRAY_CLOCK_WND_SPACING_X);
579
580 TextOut(hDC,
581 ((rcClient->right - LineSizes[szLinesIndex].cx) / 2) + HShift,
582 rcClient->top + TRAY_CLOCK_WND_SPACING_Y,
583 szLines[szLinesIndex],
584 wcslen(szLines[szLinesIndex]));
585
586 rcClient->top += LineSizes[LineNumber].cy + LineSpacing;
587 }
588
SetFont(IN HFONT hNewFont,IN BOOL bRedraw)589 VOID CTrayClockWnd::SetFont(IN HFONT hNewFont, IN BOOL bRedraw)
590 {
591 hFont = hNewFont;
592 LinesMeasured = MeasureLines();
593 if (bRedraw)
594 {
595 InvalidateRect(NULL, TRUE);
596 }
597 }
598
DrawBackground(HDC hdc)599 LRESULT CTrayClockWnd::DrawBackground(HDC hdc)
600 {
601 RECT rect;
602
603 GetClientRect(&rect);
604 DrawThemeParentBackground(m_hWnd, hdc, &rect);
605
606 return TRUE;
607 }
608
OnEraseBackground(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)609 LRESULT CTrayClockWnd::OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
610 {
611 HDC hdc = (HDC) wParam;
612
613 if (!IsAppThemed())
614 {
615 bHandled = FALSE;
616 return 0;
617 }
618
619 return DrawBackground(hdc);
620 }
621
OnTimer(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)622 LRESULT CTrayClockWnd::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
623 {
624 switch (wParam)
625 {
626 case ID_TRAYCLOCK_TIMER:
627 Update();
628 break;
629
630 case ID_TRAYCLOCK_TIMER_INIT:
631 CalibrateTimer();
632 break;
633 }
634 return TRUE;
635 }
636
OnGetMinimumSize(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)637 LRESULT CTrayClockWnd::OnGetMinimumSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
638 {
639 IsHorizontal = (BOOL) wParam;
640
641 return (LRESULT) GetMinimumSize((BOOL) wParam, (PSIZE) lParam) != 0;
642 }
643
OnContextMenu(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)644 LRESULT CTrayClockWnd::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
645 {
646 return GetParent().SendMessage(uMsg, wParam, lParam);
647 }
648
OnSetFont(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)649 LRESULT CTrayClockWnd::OnSetFont(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
650 {
651 SetFont((HFONT) wParam, (BOOL) LOWORD(lParam));
652 return TRUE;
653 }
654
OnCreate(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)655 LRESULT CTrayClockWnd::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
656 {
657 m_tooltip.Create(m_hWnd, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP);
658
659 TOOLINFOW ti = { 0 };
660 ti.cbSize = TTTOOLINFOW_V1_SIZE;
661 ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
662 ti.hwnd = m_hWnd;
663 ti.uId = reinterpret_cast<UINT_PTR>(m_hWnd);
664 ti.lpszText = NULL;
665 ti.lParam = NULL;
666
667 m_tooltip.AddTool(&ti);
668
669 if (!g_TaskbarSettings.sr.HideClock)
670 {
671 ResetTime();
672 }
673
674 /* Update the time */
675 Update();
676
677 return TRUE;
678 }
679
OnSize(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)680 LRESULT CTrayClockWnd::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
681 {
682 SIZE szClient;
683
684 szClient.cx = LOWORD(lParam);
685 szClient.cy = HIWORD(lParam);
686
687 VisibleLines = GetMinimumSize(IsHorizontal, &szClient);
688 CurrentSize = szClient;
689
690 UpdateWnd();
691 return TRUE;
692 }
693
OnTaskbarSettingsChanged(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)694 LRESULT CTrayClockWnd::OnTaskbarSettingsChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
695 {
696 BOOL bRealign = FALSE;
697
698 TaskbarSettings* newSettings = (TaskbarSettings*)lParam;
699 if (newSettings->bShowSeconds != g_TaskbarSettings.bShowSeconds)
700 {
701 g_TaskbarSettings.bShowSeconds = newSettings->bShowSeconds;
702 if (!g_TaskbarSettings.sr.HideClock)
703 {
704 bRealign = TRUE;
705
706 ResetTime();
707 }
708 }
709
710 if (newSettings->sr.HideClock != g_TaskbarSettings.sr.HideClock)
711 {
712 g_TaskbarSettings.sr.HideClock = newSettings->sr.HideClock;
713 ShowWindow(g_TaskbarSettings.sr.HideClock ? SW_HIDE : SW_SHOW);
714 bRealign = TRUE;
715
716 if (g_TaskbarSettings.sr.HideClock)
717 {
718 /* Disable all timers */
719 if (IsTimerEnabled)
720 {
721 KillTimer(ID_TRAYCLOCK_TIMER);
722 IsTimerEnabled = FALSE;
723 }
724 else if (IsInitTimerEnabled)
725 {
726 KillTimer(ID_TRAYCLOCK_TIMER_INIT);
727 IsInitTimerEnabled = FALSE;
728 }
729 }
730 else
731 {
732 ResetTime();
733 }
734 }
735
736 if (newSettings->bPreferDate != g_TaskbarSettings.bPreferDate)
737 {
738 g_TaskbarSettings.bPreferDate = newSettings->bPreferDate;
739 bRealign = TRUE;
740 }
741
742 if (bRealign)
743 {
744 /* Ask the parent to resize */
745 NMHDR nmh = {GetParent(), 0, NTNWM_REALIGN};
746 GetParent().SendMessage(WM_NOTIFY, 0, (LPARAM) &nmh);
747 Update();
748 }
749 return 0;
750 }
751
OnLButtonDblClick(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)752 LRESULT CTrayClockWnd::OnLButtonDblClick(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
753 {
754 if (IsWindowVisible())
755 {
756 //FIXME: use SHRunControlPanel
757 ShellExecuteW(m_hWnd, NULL, L"timedate.cpl", NULL, NULL, SW_NORMAL);
758 }
759 return TRUE;
760 }
761
Initialize(IN HWND hWndParent)762 HRESULT CTrayClockWnd::Initialize(IN HWND hWndParent)
763 {
764 IsHorizontal = TRUE;
765
766 /* Create the window. The tray window is going to move it to the correct
767 position and resize it as needed. */
768 DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS;
769 if (!g_TaskbarSettings.sr.HideClock)
770 dwStyle |= WS_VISIBLE;
771
772 Create(hWndParent, 0, NULL, dwStyle);
773 if (!m_hWnd)
774 return E_FAIL;
775
776 SetWindowTheme(m_hWnd, L"TrayNotify", NULL);
777
778 return S_OK;
779
780 };
781
CTrayClockWnd_CreateInstance(HWND hwndParent,REFIID riid,void ** ppv)782 HRESULT CTrayClockWnd_CreateInstance(HWND hwndParent, REFIID riid, void **ppv)
783 {
784 return ShellObjectCreatorInit<CTrayClockWnd>(hwndParent, riid, ppv);
785 }
786