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