Reactos
at master 786 lines 20 kB view raw
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 28const 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}; 38const 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 45static const WCHAR szTrayClockWndClass[] = L"TrayClockWClass"; 46 47class 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 76public: 77 CTrayClockWnd(); 78 virtual ~CTrayClockWnd(); 79 80private: 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 106public: 107 // *** IOleWindow methods *** 108 109 STDMETHODIMP 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 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 158CTrayClockWnd::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} 171CTrayClockWnd::~CTrayClockWnd() { } 172 173LRESULT 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 200LRESULT CTrayClockWnd::OnThemeChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 201{ 202 return OnThemeChanged(); 203} 204 205BOOL 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 261WORD 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 318VOID 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 413VOID CTrayClockWnd::Update() 414{ 415 GetLocalTime(&LocalTime); 416 UpdateWnd(); 417} 418 419UINT 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 431BOOL 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 456VOID 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 498LRESULT 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 513LRESULT 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 572VOID 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 589VOID 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 599LRESULT CTrayClockWnd::DrawBackground(HDC hdc) 600{ 601 RECT rect; 602 603 GetClientRect(&rect); 604 DrawThemeParentBackground(m_hWnd, hdc, &rect); 605 606 return TRUE; 607} 608 609LRESULT 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 622LRESULT 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 637LRESULT 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 644LRESULT CTrayClockWnd::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 645{ 646 return GetParent().SendMessage(uMsg, wParam, lParam); 647} 648 649LRESULT CTrayClockWnd::OnSetFont(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 650{ 651 SetFont((HFONT) wParam, (BOOL) LOWORD(lParam)); 652 return TRUE; 653} 654 655LRESULT 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 (!GetHideClock()) 670 { 671 ResetTime(); 672 } 673 674 /* Update the time */ 675 Update(); 676 677 return TRUE; 678} 679 680LRESULT 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 694LRESULT CTrayClockWnd::OnTaskbarSettingsChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 695{ 696 BOOL bRealign = FALSE; 697 BOOL bHideClock = GetHideClock(); 698 TaskbarSettings* newSettings = (TaskbarSettings*)lParam; 699 700 if (newSettings->sr.HideClock != !IsWindowVisible()) 701 { 702 g_TaskbarSettings.sr.HideClock = newSettings->sr.HideClock; 703 bHideClock = GetHideClock(); 704 ShowWindow(bHideClock ? SW_HIDE : SW_SHOW); 705 bRealign = TRUE; 706 707 if (bHideClock) 708 { 709 /* Disable all timers */ 710 if (IsTimerEnabled) 711 { 712 KillTimer(ID_TRAYCLOCK_TIMER); 713 IsTimerEnabled = FALSE; 714 } 715 else if (IsInitTimerEnabled) 716 { 717 KillTimer(ID_TRAYCLOCK_TIMER_INIT); 718 IsInitTimerEnabled = FALSE; 719 } 720 } 721 else 722 { 723 ResetTime(); 724 } 725 } 726 727 if (newSettings->bShowSeconds != g_TaskbarSettings.bShowSeconds) 728 { 729 g_TaskbarSettings.bShowSeconds = newSettings->bShowSeconds; 730 if (!bHideClock) 731 { 732 bRealign = TRUE; 733 ResetTime(); 734 } 735 } 736 737 if (newSettings->bPreferDate != g_TaskbarSettings.bPreferDate) 738 { 739 g_TaskbarSettings.bPreferDate = newSettings->bPreferDate; 740 bRealign = TRUE; 741 } 742 743 if (bRealign) 744 { 745 /* Ask the parent to resize */ 746 NMHDR nmh = {GetParent(), 0, NTNWM_REALIGN}; 747 GetParent().SendMessage(WM_NOTIFY, 0, (LPARAM) &nmh); 748 Update(); 749 } 750 return 0; 751} 752 753LRESULT CTrayClockWnd::OnLButtonDblClick(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 754{ 755 if (IsWindowVisible()) 756 { 757 //FIXME: use SHRunControlPanel 758 ShellExecuteW(m_hWnd, NULL, L"timedate.cpl", NULL, NULL, SW_NORMAL); 759 } 760 return TRUE; 761} 762 763HRESULT CTrayClockWnd::Initialize(IN HWND hWndParent) 764{ 765 IsHorizontal = TRUE; 766 767 /* Create the window. The tray window is going to move it to the correct 768 position and resize it as needed. */ 769 DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS; 770 if (!GetHideClock()) 771 dwStyle |= WS_VISIBLE; 772 773 Create(hWndParent, 0, NULL, dwStyle); 774 if (!m_hWnd) 775 return E_FAIL; 776 777 SetWindowTheme(m_hWnd, L"TrayNotify", NULL); 778 779 return S_OK; 780 781}; 782 783HRESULT CTrayClockWnd_CreateInstance(HWND hwndParent, REFIID riid, void **ppv) 784{ 785 return ShellObjectCreatorInit<CTrayClockWnd>(hwndParent, riid, ppv); 786}