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 for (i = 0; i < CLOCKWND_FORMAT_COUNT; i++) 271 { 272 if (LineSizes[i].cx != 0) 273 { 274 if (iLinesVisible > 0) 275 { 276 if (Horizontal) 277 { 278 if (szMax.cy + LineSizes[i].cy + (LONG) LineSpacing > 279 pSize->cy - (2 * TRAY_CLOCK_WND_SPACING_Y)) 280 { 281 break; 282 } 283 } 284 else 285 { 286 if (LineSizes[i].cx > pSize->cx - (2 * TRAY_CLOCK_WND_SPACING_X)) 287 break; 288 } 289 290 /* Add line spacing */ 291 szMax.cy += LineSpacing; 292 } 293 294 iLinesVisible++; 295 296 /* Increase maximum rectangle */ 297 szMax.cy += LineSizes[i].cy; 298 if (LineSizes[i].cx > szMax.cx) 299 szMax.cx = LineSizes[i].cx; 300 } 301 } 302 303 szMax.cx += 2 * TRAY_CLOCK_WND_SPACING_X; 304 szMax.cy += 2 * TRAY_CLOCK_WND_SPACING_Y; 305 306 *pSize = szMax; 307 308 return iLinesVisible; 309 } 310 311 VOID CTrayClockWnd::UpdateWnd() 312 { 313 SIZE szPrevCurrent; 314 UINT BufSize, i; 315 INT iRet; 316 RECT rcClient; 317 318 ZeroMemory(LineSizes, sizeof(LineSizes)); 319 320 szPrevCurrent = CurrentSize; 321 322 for (i = 0; i < CLOCKWND_FORMAT_COUNT; i++) 323 { 324 szLines[i][0] = L'\0'; 325 BufSize = _countof(szLines[0]); 326 327 if (ClockWndFormats[i].IsTime) 328 { 329 iRet = GetTimeFormat(LOCALE_USER_DEFAULT, 330 g_TaskbarSettings.bShowSeconds ? ClockWndFormats[i].dwFormatFlags : TIME_NOSECONDS, 331 &LocalTime, 332 ClockWndFormats[i].lpFormat, 333 szLines[i], 334 BufSize); 335 } 336 else 337 { 338 iRet = GetDateFormat(LOCALE_USER_DEFAULT, 339 ClockWndFormats[i].dwFormatFlags, 340 &LocalTime, 341 ClockWndFormats[i].lpFormat, 342 szLines[i], 343 BufSize); 344 } 345 346 if (iRet != 0 && i == 0) 347 { 348 /* Set the window text to the time only */ 349 SetWindowText(szLines[i]); 350 } 351 } 352 353 LinesMeasured = MeasureLines(); 354 355 if (LinesMeasured && 356 GetClientRect(&rcClient)) 357 { 358 SIZE szWnd; 359 360 szWnd.cx = rcClient.right; 361 szWnd.cy = rcClient.bottom; 362 363 VisibleLines = GetMinimumSize(IsHorizontal, &szWnd); 364 CurrentSize = szWnd; 365 } 366 367 if (IsWindowVisible()) 368 { 369 InvalidateRect(NULL, TRUE); 370 371 if (szPrevCurrent.cx != CurrentSize.cx || 372 szPrevCurrent.cy != CurrentSize.cy) 373 { 374 /* Ask the parent to resize */ 375 NMHDR nmh = {GetParent(), 0, NTNWM_REALIGN}; 376 GetParent().SendMessage(WM_NOTIFY, 0, (LPARAM) &nmh); 377 } 378 } 379 380 int iDateLength = GetDateFormat(LOCALE_USER_DEFAULT, 381 DATE_LONGDATE, 382 &LocalTime, 383 NULL, 384 NULL, 385 0); 386 if (iDateLength <= 0) 387 { 388 return; 389 } 390 391 WCHAR* szDate = new WCHAR[iDateLength]; 392 if (GetDateFormat(LOCALE_USER_DEFAULT, 393 DATE_LONGDATE, 394 &LocalTime, 395 NULL, 396 szDate, 397 iDateLength) > 0) 398 { 399 m_tooltip.UpdateTipText(m_hWnd, 400 reinterpret_cast<UINT_PTR>(m_hWnd), 401 szDate); 402 } 403 delete[] szDate; 404 } 405 406 VOID CTrayClockWnd::Update() 407 { 408 GetLocalTime(&LocalTime); 409 UpdateWnd(); 410 } 411 412 UINT CTrayClockWnd::CalculateDueTime() 413 { 414 UINT uiDueTime; 415 416 GetLocalTime(&LocalTime); 417 uiDueTime = 1000 - (UINT) LocalTime.wMilliseconds; 418 if (!g_TaskbarSettings.bShowSeconds) 419 uiDueTime += (59 - (UINT) LocalTime.wSecond) * 1000; 420 421 return uiDueTime; 422 } 423 424 BOOL CTrayClockWnd::ResetTime() 425 { 426 UINT uiDueTime; 427 BOOL Ret; 428 429 /* Disable all timers */ 430 if (IsTimerEnabled) 431 { 432 KillTimer(ID_TRAYCLOCK_TIMER); 433 IsTimerEnabled = FALSE; 434 } 435 else if (IsInitTimerEnabled) 436 { 437 KillTimer(ID_TRAYCLOCK_TIMER_INIT); 438 } 439 440 uiDueTime = CalculateDueTime(); 441 442 /* Set the new timer */ 443 Ret = SetTimer(ID_TRAYCLOCK_TIMER_INIT, uiDueTime, NULL) != 0; 444 IsInitTimerEnabled = Ret; 445 446 return Ret; 447 } 448 449 VOID CTrayClockWnd::CalibrateTimer() 450 { 451 UINT uiDueTime; 452 BOOL Ret; 453 UINT uiWait1, uiWait2; 454 455 /* Kill the initialization timer */ 456 KillTimer(ID_TRAYCLOCK_TIMER_INIT); 457 IsInitTimerEnabled = FALSE; 458 459 uiDueTime = CalculateDueTime(); 460 461 if (g_TaskbarSettings.bShowSeconds) 462 { 463 uiWait1 = 1000 - 200; 464 uiWait2 = 1000; 465 } 466 else 467 { 468 uiWait1 = 60 * 1000 - 200; 469 uiWait2 = 60 * 1000; 470 } 471 472 if (uiDueTime > uiWait1) 473 { 474 /* The update of the clock will be up to 200 ms late, but that's 475 acceptable. We're going to setup a timer that fires depending 476 uiWait2. */ 477 Ret = SetTimer(ID_TRAYCLOCK_TIMER, uiWait2, NULL) != 0; 478 IsTimerEnabled = Ret; 479 } 480 else 481 { 482 /* Recalibrate the timer and recalculate again when the current 483 minute/second ends. */ 484 ResetTime(); 485 } 486 487 /* Update the time */ 488 Update(); 489 } 490 491 LRESULT CTrayClockWnd::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 492 { 493 /* Disable all timers */ 494 if (IsTimerEnabled) 495 { 496 KillTimer(ID_TRAYCLOCK_TIMER); 497 } 498 else if (IsInitTimerEnabled) 499 { 500 KillTimer(ID_TRAYCLOCK_TIMER_INIT); 501 } 502 503 return TRUE; 504 } 505 506 LRESULT CTrayClockWnd::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 507 { 508 RECT rcClient; 509 HFONT hPrevFont; 510 INT iPrevBkMode; 511 UINT i, line; 512 PAINTSTRUCT ps; 513 HDC hDC = (HDC) wParam; 514 515 if (wParam == 0) 516 hDC = BeginPaint(&ps); 517 518 if (hDC == NULL) 519 return FALSE; 520 521 if (LinesMeasured && 522 GetClientRect(&rcClient)) 523 { 524 iPrevBkMode = SetBkMode(hDC, TRANSPARENT); 525 526 if (!IsAppThemed()) 527 textColor = ::GetSysColor(COLOR_BTNTEXT); 528 529 ::SetTextColor(hDC, textColor); 530 531 hPrevFont = (HFONT) SelectObject(hDC, hFont); 532 533 rcClient.top = (rcClient.bottom - CurrentSize.cy) / 2; 534 rcClient.bottom = rcClient.top + CurrentSize.cy; 535 536 if (VisibleLines == 2) 537 { 538 /* Display either time and weekday (by default), or time and date (opt-in) */ 539 PaintLine(hDC, &rcClient, 0, CLOCKWND_FORMAT_TIME); 540 PaintLine(hDC, &rcClient, 1, 541 g_TaskbarSettings.bPreferDate ? CLOCKWND_FORMAT_DATE : CLOCKWND_FORMAT_DAY); 542 } 543 else 544 { 545 for (i = 0, line = 0; 546 i < CLOCKWND_FORMAT_COUNT && line < VisibleLines; 547 i++) 548 { 549 PaintLine(hDC, &rcClient, i, i); 550 line++; 551 } 552 } 553 554 SelectObject(hDC, hPrevFont); 555 556 SetBkMode(hDC, iPrevBkMode); 557 } 558 559 if (wParam == 0) 560 EndPaint(&ps); 561 562 return TRUE; 563 } 564 565 VOID CTrayClockWnd::PaintLine(IN HDC hDC, IN OUT RECT *rcClient, IN UINT LineNumber, IN UINT szLinesIndex) 566 { 567 if (LineSizes[LineNumber].cx == 0) 568 return; 569 570 TextOut(hDC, 571 (rcClient->right - LineSizes[szLinesIndex].cx) / 2, 572 rcClient->top + TRAY_CLOCK_WND_SPACING_Y, 573 szLines[szLinesIndex], 574 wcslen(szLines[szLinesIndex])); 575 576 rcClient->top += LineSizes[LineNumber].cy + LineSpacing; 577 } 578 579 VOID CTrayClockWnd::SetFont(IN HFONT hNewFont, IN BOOL bRedraw) 580 { 581 hFont = hNewFont; 582 LinesMeasured = MeasureLines(); 583 if (bRedraw) 584 { 585 InvalidateRect(NULL, TRUE); 586 } 587 } 588 589 LRESULT CTrayClockWnd::DrawBackground(HDC hdc) 590 { 591 RECT rect; 592 593 GetClientRect(&rect); 594 DrawThemeParentBackground(m_hWnd, hdc, &rect); 595 596 return TRUE; 597 } 598 599 LRESULT CTrayClockWnd::OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 600 { 601 HDC hdc = (HDC) wParam; 602 603 if (!IsAppThemed()) 604 { 605 bHandled = FALSE; 606 return 0; 607 } 608 609 return DrawBackground(hdc); 610 } 611 612 LRESULT CTrayClockWnd::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 613 { 614 switch (wParam) 615 { 616 case ID_TRAYCLOCK_TIMER: 617 Update(); 618 break; 619 620 case ID_TRAYCLOCK_TIMER_INIT: 621 CalibrateTimer(); 622 break; 623 } 624 return TRUE; 625 } 626 627 LRESULT CTrayClockWnd::OnGetMinimumSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 628 { 629 IsHorizontal = (BOOL) wParam; 630 631 return (LRESULT) GetMinimumSize((BOOL) wParam, (PSIZE) lParam) != 0; 632 } 633 634 LRESULT CTrayClockWnd::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 635 { 636 return GetParent().SendMessage(uMsg, wParam, lParam); 637 } 638 639 LRESULT CTrayClockWnd::OnSetFont(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 640 { 641 SetFont((HFONT) wParam, (BOOL) LOWORD(lParam)); 642 return TRUE; 643 } 644 645 LRESULT CTrayClockWnd::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 646 { 647 m_tooltip.Create(m_hWnd, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP); 648 649 TOOLINFOW ti = { 0 }; 650 ti.cbSize = TTTOOLINFOW_V1_SIZE; 651 ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS; 652 ti.hwnd = m_hWnd; 653 ti.uId = reinterpret_cast<UINT_PTR>(m_hWnd); 654 ti.lpszText = NULL; 655 ti.lParam = NULL; 656 657 m_tooltip.AddTool(&ti); 658 659 if (!g_TaskbarSettings.sr.HideClock) 660 { 661 ResetTime(); 662 } 663 664 /* Update the time */ 665 Update(); 666 667 return TRUE; 668 } 669 670 LRESULT CTrayClockWnd::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 671 { 672 SIZE szClient; 673 674 szClient.cx = LOWORD(lParam); 675 szClient.cy = HIWORD(lParam); 676 677 VisibleLines = GetMinimumSize(IsHorizontal, &szClient); 678 CurrentSize = szClient; 679 680 InvalidateRect(NULL, TRUE); 681 return TRUE; 682 } 683 684 LRESULT CTrayClockWnd::OnTaskbarSettingsChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 685 { 686 BOOL bRealign = FALSE; 687 688 TaskbarSettings* newSettings = (TaskbarSettings*)lParam; 689 if (newSettings->bShowSeconds != g_TaskbarSettings.bShowSeconds) 690 { 691 g_TaskbarSettings.bShowSeconds = newSettings->bShowSeconds; 692 if (!g_TaskbarSettings.sr.HideClock) 693 { 694 bRealign = TRUE; 695 696 ResetTime(); 697 } 698 } 699 700 if (newSettings->sr.HideClock != g_TaskbarSettings.sr.HideClock) 701 { 702 g_TaskbarSettings.sr.HideClock = newSettings->sr.HideClock; 703 ShowWindow(g_TaskbarSettings.sr.HideClock ? SW_HIDE : SW_SHOW); 704 bRealign = TRUE; 705 706 if (g_TaskbarSettings.sr.HideClock) 707 { 708 /* Disable all timers */ 709 if (IsTimerEnabled) 710 { 711 KillTimer(ID_TRAYCLOCK_TIMER); 712 IsTimerEnabled = FALSE; 713 } 714 else if (IsInitTimerEnabled) 715 { 716 KillTimer(ID_TRAYCLOCK_TIMER_INIT); 717 IsInitTimerEnabled = FALSE; 718 } 719 } 720 else 721 { 722 ResetTime(); 723 } 724 } 725 726 if (newSettings->bPreferDate != g_TaskbarSettings.bPreferDate) 727 { 728 g_TaskbarSettings.bPreferDate = newSettings->bPreferDate; 729 bRealign = TRUE; 730 } 731 732 if (bRealign) 733 { 734 /* Ask the parent to resize */ 735 NMHDR nmh = {GetParent(), 0, NTNWM_REALIGN}; 736 GetParent().SendMessage(WM_NOTIFY, 0, (LPARAM) &nmh); 737 Update(); 738 } 739 return 0; 740 } 741 742 LRESULT CTrayClockWnd::OnLButtonDblClick(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 743 { 744 if (IsWindowVisible()) 745 { 746 //FIXME: use SHRunControlPanel 747 ShellExecuteW(m_hWnd, NULL, L"timedate.cpl", NULL, NULL, SW_NORMAL); 748 } 749 return TRUE; 750 } 751 752 HRESULT CTrayClockWnd::Initialize(IN HWND hWndParent) 753 { 754 IsHorizontal = TRUE; 755 756 /* Create the window. The tray window is going to move it to the correct 757 position and resize it as needed. */ 758 DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS; 759 if (!g_TaskbarSettings.sr.HideClock) 760 dwStyle |= WS_VISIBLE; 761 762 Create(hWndParent, 0, NULL, dwStyle); 763 if (!m_hWnd) 764 return E_FAIL; 765 766 SetWindowTheme(m_hWnd, L"TrayNotify", NULL); 767 768 return S_OK; 769 770 }; 771 772 HRESULT CTrayClockWnd_CreateInstance(HWND hwndParent, REFIID riid, void **ppv) 773 { 774 return ShellObjectCreatorInit<CTrayClockWnd>(hwndParent, riid, ppv); 775 } 776