diff --git a/base/shell/explorer/CMakeLists.txt b/base/shell/explorer/CMakeLists.txt index 222d3a6653a..35664b5b39d 100644 --- a/base/shell/explorer/CMakeLists.txt +++ b/base/shell/explorer/CMakeLists.txt @@ -22,6 +22,7 @@ list(APPEND SOURCE taskswnd.cpp tbsite.cpp trayclock.cpp + traydeskbtn.cpp trayntfy.cpp trayprop.cpp traywnd.cpp diff --git a/base/shell/explorer/precomp.h b/base/shell/explorer/precomp.h index fa6a34df2b6..df60ef3a6f5 100644 --- a/base/shell/explorer/precomp.h +++ b/base/shell/explorer/precomp.h @@ -369,6 +369,7 @@ HRESULT CTrayClockWnd_CreateInstance(HWND hwndParent, REFIID riid, void **ppv); /* TrayNotifyWnd */ #define TNWM_GETMINIMUMSIZE (WM_USER + 0x100) #define TNWM_CHANGETRAYPOS (WM_USER + 0x104) +#define TNWM_GETSHOWDESKTOPBUTTON (WM_USER + 0x7601) #define NTNWM_REALIGN (0x1) @@ -377,6 +378,8 @@ HRESULT CTrayNotifyWnd_CreateInstance(HWND hwndParent, REFIID riid, void **ppv); /* SysPagerWnd */ HRESULT CSysPagerWnd_CreateInstance(HWND hwndParent, REFIID riid, void **ppv); +#include "traydeskbtn.h" + /* * taskswnd.c */ diff --git a/base/shell/explorer/traydeskbtn.cpp b/base/shell/explorer/traydeskbtn.cpp new file mode 100644 index 00000000000..bb448f2495d --- /dev/null +++ b/base/shell/explorer/traydeskbtn.cpp @@ -0,0 +1,382 @@ +/* + * PROJECT: ReactOS Explorer + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: Show Desktop tray button implementation + * COPYRIGHT: Copyright 2006-2007 Thomas Weidenmueller + * Copyright 2018-2022 Katayama Hirofumi MZ + * Copyright 2023 Ethan Rodensky + */ + +#include "precomp.h" +#include +#include + +#define IDI_SHELL32_DESKTOP 35 +#define IDI_IMAGERES_DESKTOP 110 + +#define SHOW_DESKTOP_TIMER_ID 999 +#define SHOW_DESKTOP_TIMER_INTERVAL 200 + +CTrayShowDesktopButton::CTrayShowDesktopButton() : + m_nClickedTime(0), + m_inset({2, 2}), + m_icon(NULL), + m_highContrastMode(FALSE), + m_drawWithDedicatedBackground(FALSE), + m_bHovering(FALSE), + m_hWndTaskbar(NULL), + m_bPressed(FALSE), + m_bHorizontal(FALSE) +{ +} + +INT CTrayShowDesktopButton::WidthOrHeight() const +{ + if (IsThemeActive() && !m_highContrastMode) + { + if (m_drawWithDedicatedBackground) + { + if (GetSystemMetrics(SM_TABLETPC)) + { + //TODO: DPI scaling - return logical-to-physical conversion of 24, not fixed value + return 24; + } + else + return 15; + } + else + { + INT CurMargin = m_bHorizontal + ? (m_ContentMargins.cxLeftWidth + m_ContentMargins.cxRightWidth) + : (m_ContentMargins.cyTopHeight + m_ContentMargins.cyBottomHeight); + return max(16 + CurMargin, 18) + 6; + } + } + else + { + return max(2 * GetSystemMetrics(SM_CXBORDER) + GetSystemMetrics(SM_CXSMICON), + 2 * GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYSMICON)); + } +} + +HRESULT CTrayShowDesktopButton::DoCreate(HWND hwndParent) +{ + const DWORD style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | BS_DEFPUSHBUTTON; + Create(hwndParent, NULL, NULL, style); + + if (!m_hWnd) + return E_FAIL; + + // Get desktop icon + bool bIconRetrievalFailed = ExtractIconExW(L"imageres.dll", -IDI_IMAGERES_DESKTOP, NULL, &m_icon, 1) == UINT_MAX; + if (bIconRetrievalFailed || !m_icon) + ExtractIconExW(L"shell32.dll", -IDI_SHELL32_DESKTOP, NULL, &m_icon, 1); + + // Get appropriate size at which to display desktop icon + m_szIcon.cx = GetSystemMetrics(SM_CXSMICON); + m_szIcon.cy = GetSystemMetrics(SM_CYSMICON); + + // Prep visual style + EnsureWindowTheme(TRUE); + + // Get HWND of Taskbar + m_hWndTaskbar = ::GetParent(hwndParent); + if (!::IsWindow(m_hWndTaskbar)) + return E_FAIL; + + return S_OK; +} + +LRESULT CTrayShowDesktopButton::OnClick(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + // The actual action can be delayed as an expected behaviour. + // But a too late action is an unexpected behaviour. + LONG nTime0 = m_nClickedTime; + LONG nTime1 = ::GetMessageTime(); + if (nTime1 - nTime0 >= 600) // Ignore after 0.6 sec + return 0; + + // Show/Hide Desktop + ::SendMessage(m_hWndTaskbar, WM_COMMAND, TRAYCMD_TOGGLE_DESKTOP, 0); + + return 0; +} + +// This function is called from OnLButtonDown and parent. +VOID CTrayShowDesktopButton::Click() +{ + // The actual action can be delayed as an expected behaviour. + m_nClickedTime = ::GetMessageTime(); + PostMessage(TSDB_CLICK, 0, 0); +} + +LRESULT CTrayShowDesktopButton::OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + m_bPressed = FALSE; + ReleaseCapture(); + Invalidate(TRUE); + + POINT pt; + ::GetCursorPos(&pt); + if (PtInButton(&pt)) + Click(); // Left-click + return 0; +} + +LRESULT CTrayShowDesktopButton::OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + m_bPressed = TRUE; + SetCapture(); + Invalidate(TRUE); + return 0; +} + +LRESULT CTrayShowDesktopButton::OnSettingChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + LRESULT ret = OnThemeChanged(uMsg, wParam, lParam, bHandled); + EnsureWindowTheme(TRUE); + return ret; +} + +LRESULT CTrayShowDesktopButton::OnThemeChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + HIGHCONTRAST hcInfo; + hcInfo.cbSize = sizeof(hcInfo); + if (SystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof(hcInfo), &hcInfo, FALSE)) + m_highContrastMode = (hcInfo.dwFlags & HCF_HIGHCONTRASTON); + + if (m_hTheme) + { + ::CloseThemeData(m_hTheme); + m_hTheme = NULL; + } + if (m_hFallbackTheme) + { + ::CloseThemeData(m_hFallbackTheme); + m_hFallbackTheme = NULL; + } + + EnsureWindowTheme(FALSE); + + Invalidate(TRUE); + return 0; +} + +LRESULT CTrayShowDesktopButton::OnWindowPosChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + EnsureWindowTheme(TRUE); + return 0; +} + +VOID CTrayShowDesktopButton::EnsureWindowTheme(BOOL setTheme) +{ + if (setTheme) + SetWindowTheme(m_hWnd, m_bHorizontal ? L"ShowDesktop" : L"VerticalShowDesktop", NULL); + + if (::IsWindow(m_hWndTaskbar)) + { + m_hFallbackTheme = ::OpenThemeData(m_hWndTaskbar, L"Toolbar"); + GetThemeMargins(m_hFallbackTheme, NULL, TP_BUTTON, 0, TMT_CONTENTMARGINS, NULL, &m_ContentMargins); + } + else + { + m_hFallbackTheme = NULL; + } + + MARGINS contentMargins; + if (GetThemeMargins(GetWindowTheme(GetParent().m_hWnd), NULL, TNP_BACKGROUND, 0, TMT_CONTENTMARGINS, NULL, &contentMargins) == S_OK) + { + m_inset.cx = max(0, contentMargins.cxRightWidth - 5); + m_inset.cy = max(0, contentMargins.cyBottomHeight - 5); + } + else + { + m_inset.cx = 2; + m_inset.cy = 2; + } + + m_drawWithDedicatedBackground = FALSE; + if (IsThemeActive()) + { + m_hTheme = OpenThemeData(m_hWnd, L"Button"); + if (m_hTheme != NULL) + m_drawWithDedicatedBackground = !IsThemePartDefined(m_hTheme, BP_PUSHBUTTON, 0); + } +} + +LRESULT CTrayShowDesktopButton::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + RECT rc; + GetClientRect(&rc); + + PAINTSTRUCT ps; + HDC hdc = BeginPaint(&ps); + OnDraw(hdc, &rc); + EndPaint(&ps); + + return 0; +} + +LRESULT CTrayShowDesktopButton::OnPrintClient(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + if ((lParam & PRF_CHECKVISIBLE) && !IsWindowVisible()) + return 0; + + RECT rc; + GetClientRect(&rc); + + HDC hdc = (HDC)wParam; + OnDraw(hdc, &rc); + + return 0; +} + +BOOL CTrayShowDesktopButton::PtInButton(LPPOINT ppt) const +{ + if (!ppt || !IsWindow()) + return FALSE; + + RECT rc; + GetWindowRect(&rc); + INT cxEdge = ::GetSystemMetrics(SM_CXEDGE), cyEdge = ::GetSystemMetrics(SM_CYEDGE); + ::InflateRect(&rc, max(cxEdge, 1), max(cyEdge, 1)); + + return m_bHorizontal + ? (ppt->x > rc.left) + : (ppt->y > rc.top); +} + +VOID CTrayShowDesktopButton::StartHovering() +{ + if (m_bHovering) + return; + + m_bHovering = TRUE; + Invalidate(TRUE); + + SetTimer(SHOW_DESKTOP_TIMER_ID, SHOW_DESKTOP_TIMER_INTERVAL, NULL); + + ::PostMessage(m_hWndTaskbar, WM_NCPAINT, 0, 0); +} + +LRESULT CTrayShowDesktopButton::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + StartHovering(); + return 0; +} + +LRESULT CTrayShowDesktopButton::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + if (wParam != SHOW_DESKTOP_TIMER_ID || !m_bHovering) + return 0; + + POINT pt; + ::GetCursorPos(&pt); + if (!PtInButton(&pt)) // The end of hovering? + { + m_bHovering = FALSE; + KillTimer(SHOW_DESKTOP_TIMER_ID); + Invalidate(TRUE); + + ::PostMessage(m_hWndTaskbar, WM_NCPAINT, 0, 0); + } + + return 0; +} + +LRESULT CTrayShowDesktopButton::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + if (m_hTheme) + { + ::CloseThemeData(m_hTheme); + m_hTheme = NULL; + } + if (m_hFallbackTheme) + { + ::CloseThemeData(m_hFallbackTheme); + m_hFallbackTheme = NULL; + } + + return 0; +} + +VOID CTrayShowDesktopButton::OnDraw(HDC hdc, LPRECT prc) +{ + RECT rc = { prc->left, prc->top, prc->right, prc->bottom }; + LPRECT lpRc = &rc; + HBRUSH hbrBackground = NULL; + + if (m_hTheme) + { + HTHEME theme; + int part = 0; + int state = 0; + if (m_drawWithDedicatedBackground) + { + theme = m_hTheme; + + if (m_bPressed) + state = PBS_PRESSED; + else if (m_bHovering) + state = PBS_HOT; + else + state = PBS_NORMAL; + } + else + { + part = TP_BUTTON; + theme = m_hFallbackTheme; + + if (m_bPressed) + state = TS_PRESSED; + else if (m_bHovering) + state = TS_HOT; + else + state = TS_NORMAL; + + if (m_bHorizontal) + rc.right -= m_inset.cx; + else + rc.bottom -= m_inset.cy; + } + + if (::IsThemeBackgroundPartiallyTransparent(theme, part, state)) + ::DrawThemeParentBackground(m_hWnd, hdc, NULL); + + ::DrawThemeBackground(theme, hdc, part, state, lpRc, lpRc); + } + else + { + hbrBackground = ::GetSysColorBrush(COLOR_3DFACE); + ::FillRect(hdc, lpRc, hbrBackground); + + if (m_bPressed || m_bHovering) + { + UINT edge = m_bPressed ? BDR_SUNKENOUTER : BDR_RAISEDINNER; + DrawEdge(hdc, lpRc, edge, BF_RECT); + } + } + + if (m_highContrastMode || !m_drawWithDedicatedBackground) + { + /* Prepare to draw icon */ + + // Determine X-position of icon's top-left corner + int iconX = rc.left; + iconX += (rc.right - iconX) / 2; + iconX -= m_szIcon.cx / 2; + + // Determine Y-position of icon's top-left corner + int iconY = rc.top; + iconY += (rc.bottom - iconY) / 2; + iconY -= m_szIcon.cy / 2; + + // Ok now actually draw the icon itself + if (m_icon) + { + DrawIconEx(hdc, iconX, iconY, + m_icon, 0, 0, + 0, hbrBackground, DI_NORMAL); + } + } +} diff --git a/base/shell/explorer/traydeskbtn.h b/base/shell/explorer/traydeskbtn.h new file mode 100644 index 00000000000..5e59ecfa1a6 --- /dev/null +++ b/base/shell/explorer/traydeskbtn.h @@ -0,0 +1,76 @@ +/* + * PROJECT: ReactOS Explorer + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: Show Desktop tray button header file + * COPYRIGHT: Copyright 2006-2007 Thomas Weidenmueller + * Copyright 2018-2022 Katayama Hirofumi MZ + * Copyright 2023 Ethan Rodensky + */ + +#pragma once + +// This window class name is CONFIRMED on Win10 by WinHier. +static const WCHAR szTrayShowDesktopButton[] = L"TrayShowDesktopButtonWClass"; +#define TSDB_CLICK (WM_USER + 100) + +// The 'Show Desktop' button at the end of the taskbar +class CTrayShowDesktopButton : + public CWindowImpl +{ + LONG m_nClickedTime; + HTHEME m_hTheme; + HTHEME m_hFallbackTheme; + MARGINS m_ContentMargins; + SIZE m_inset; + HICON m_icon; + SIZE m_szIcon; + BOOL m_highContrastMode; + BOOL m_drawWithDedicatedBackground; + BOOL m_bHovering; + HWND m_hWndTaskbar; + +public: + BOOL m_bPressed; + BOOL m_bHorizontal; + + DECLARE_WND_CLASS_EX(szTrayShowDesktopButton, CS_HREDRAW | CS_VREDRAW, COLOR_3DFACE) + + BEGIN_MSG_MAP(CTrayShowDesktopButton) + MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown) + MESSAGE_HANDLER(WM_NCLBUTTONDOWN, OnLButtonDown) + MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) + MESSAGE_HANDLER(WM_NCLBUTTONUP, OnLButtonUp) + MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChanged) + MESSAGE_HANDLER(WM_THEMECHANGED, OnThemeChanged) + MESSAGE_HANDLER(WM_WINDOWPOSCHANGED, OnWindowPosChanged) + MESSAGE_HANDLER(WM_PAINT, OnPaint) + MESSAGE_HANDLER(WM_PRINTCLIENT, OnPrintClient) + MESSAGE_HANDLER(WM_TIMER, OnTimer) + MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) + MESSAGE_HANDLER(WM_DESTROY, OnDestroy) + MESSAGE_HANDLER(TSDB_CLICK, OnClick) + END_MSG_MAP() + + CTrayShowDesktopButton(); + INT WidthOrHeight() const; + HRESULT DoCreate(HWND hwndParent); + VOID Click(); + BOOL PtInButton(LPPOINT pt) const; + VOID StartHovering(); + LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + +private: + // This function is called from OnPaint and parent. + VOID OnDraw(HDC hdc, LPRECT prc); + LRESULT OnClick(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT OnSettingChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT OnThemeChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT OnWindowPosChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + VOID EnsureWindowTheme(BOOL setTheme); + LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT OnPrintClient(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); +}; diff --git a/base/shell/explorer/trayntfy.cpp b/base/shell/explorer/trayntfy.cpp index 9a279240f3c..ed40b9a5082 100644 --- a/base/shell/explorer/trayntfy.cpp +++ b/base/shell/explorer/trayntfy.cpp @@ -20,15 +20,17 @@ */ #include "precomp.h" - -/* - * TrayNotifyWnd - */ +#include static const WCHAR szTrayNotifyWndClass[] = L"TrayNotifyWnd"; #define TRAY_NOTIFY_WND_SPACING_X 1 #define TRAY_NOTIFY_WND_SPACING_Y 1 +#define CLOCK_TEXT_HACK 4 + +/* + * TrayNotifyWnd + */ class CTrayNotifyWnd : public CComCoClass, @@ -37,14 +39,17 @@ class CTrayNotifyWnd : public IOleWindow { CComPtr m_clock; + CTrayShowDesktopButton m_ShowDesktopButton; CComPtr m_pager; HWND m_hwndClock; + HWND m_hwndShowDesktop; HWND m_hwndPager; HTHEME TrayTheme; - SIZE szTrayClockMin; - SIZE szTrayNotify; + SIZE trayClockMinSize; + SIZE trayShowDesktopSize; + SIZE trayNotifySize; MARGINS ContentMargin; BOOL IsHorizontal; @@ -55,11 +60,12 @@ public: TrayTheme(NULL), IsHorizontal(FALSE) { - ZeroMemory(&szTrayClockMin, sizeof(szTrayClockMin)); - ZeroMemory(&szTrayNotify, sizeof(szTrayNotify)); + ZeroMemory(&trayClockMinSize, sizeof(trayClockMinSize)); + ZeroMemory(&trayShowDesktopSize, sizeof(trayShowDesktopSize)); + ZeroMemory(&trayNotifySize, sizeof(trayNotifySize)); ZeroMemory(&ContentMargin, sizeof(ContentMargin)); } - virtual ~CTrayNotifyWnd() { } + ~CTrayNotifyWnd() { } LRESULT OnThemeChanged() { @@ -121,58 +127,83 @@ public: if (FAILED_UNEXPECTEDLY(hr)) return FALSE; + /* Create the 'Show Desktop' button */ + m_ShowDesktopButton.DoCreate(m_hWnd); + m_hwndShowDesktop = m_ShowDesktopButton.m_hWnd; + return TRUE; } BOOL GetMinimumSize(IN OUT PSIZE pSize) { - SIZE szClock = { 0, 0 }; - SIZE szTray = { 0, 0 }; + SIZE clockSize = { 0, 0 }; + SIZE traySize = { 0, 0 }; + SIZE showDesktopSize = { 0, 0 }; if (!g_TaskbarSettings.sr.HideClock) { if (IsHorizontal) { - szClock.cy = pSize->cy - 2 * TRAY_NOTIFY_WND_SPACING_Y; - if (szClock.cy <= 0) + clockSize.cy = pSize->cy; + if (clockSize.cy <= 0) goto NoClock; } else { - szClock.cx = pSize->cx - 2 * TRAY_NOTIFY_WND_SPACING_X; - if (szClock.cx <= 0) + clockSize.cx = pSize->cx; + if (clockSize.cx <= 0) goto NoClock; } - ::SendMessage(m_hwndClock, TNWM_GETMINIMUMSIZE, (WPARAM) IsHorizontal, (LPARAM) &szClock); + ::SendMessage(m_hwndClock, TNWM_GETMINIMUMSIZE, (WPARAM) IsHorizontal, (LPARAM) &clockSize); - szTrayClockMin = szClock; + trayClockMinSize = clockSize; } else NoClock: - szTrayClockMin = szClock; + trayClockMinSize = clockSize; if (IsHorizontal) { - szTray.cy = pSize->cy - 2 * TRAY_NOTIFY_WND_SPACING_Y; + traySize.cy = pSize->cy - 2 * TRAY_NOTIFY_WND_SPACING_Y; } else { - szTray.cx = pSize->cx - 2 * TRAY_NOTIFY_WND_SPACING_X; + traySize.cx = pSize->cx - 2 * TRAY_NOTIFY_WND_SPACING_X; } - ::SendMessage(m_hwndPager, TNWM_GETMINIMUMSIZE, (WPARAM) IsHorizontal, (LPARAM) &szTray); + ::SendMessage(m_hwndPager, TNWM_GETMINIMUMSIZE, (WPARAM) IsHorizontal, (LPARAM) &traySize); - szTrayNotify = szTray; + trayNotifySize = traySize; + + INT showDesktopButtonExtent = 0; + if (g_TaskbarSettings.bShowDesktopButton) + { + showDesktopButtonExtent = m_ShowDesktopButton.WidthOrHeight(); + if (IsHorizontal) + { + showDesktopSize.cx = showDesktopButtonExtent; + showDesktopSize.cy = pSize->cy; + } + else + { + showDesktopSize.cx = pSize->cx; + showDesktopSize.cy = showDesktopButtonExtent; + } + } + trayShowDesktopSize = showDesktopSize; if (IsHorizontal) { pSize->cx = 2 * TRAY_NOTIFY_WND_SPACING_X; if (!g_TaskbarSettings.sr.HideClock) - pSize->cx += TRAY_NOTIFY_WND_SPACING_X + szTrayClockMin.cx; + pSize->cx += TRAY_NOTIFY_WND_SPACING_X + trayClockMinSize.cx; - pSize->cx += szTray.cx; + if (g_TaskbarSettings.bShowDesktopButton) + pSize->cx += showDesktopButtonExtent; + + pSize->cx += traySize.cx; pSize->cx += ContentMargin.cxLeftWidth + ContentMargin.cxRightWidth; } else @@ -180,56 +211,140 @@ public: pSize->cy = 2 * TRAY_NOTIFY_WND_SPACING_Y; if (!g_TaskbarSettings.sr.HideClock) - pSize->cy += TRAY_NOTIFY_WND_SPACING_Y + szTrayClockMin.cy; + pSize->cy += TRAY_NOTIFY_WND_SPACING_Y + trayClockMinSize.cy; - pSize->cy += szTray.cy; + if (g_TaskbarSettings.bShowDesktopButton) + pSize->cy += showDesktopButtonExtent; + + pSize->cy += traySize.cy; pSize->cy += ContentMargin.cyTopHeight + ContentMargin.cyBottomHeight; } return TRUE; } - VOID Size(IN const SIZE *pszClient) + VOID Size(IN OUT SIZE *pszClient) { - if (!g_TaskbarSettings.sr.HideClock) - { - POINT ptClock; - SIZE szClock; + RECT rcClient = {0, 0, pszClient->cx, pszClient->cy}; + AlignControls(&rcClient); + pszClient->cx = rcClient.right - rcClient.left; + pszClient->cy = rcClient.bottom - rcClient.top; + } + VOID AlignControls(IN CONST PRECT prcClient OPTIONAL) + { + RECT rcClient; + if (prcClient != NULL) + rcClient = *prcClient; + else + GetClientRect(&rcClient); + + rcClient.left += ContentMargin.cxLeftWidth; + rcClient.top += ContentMargin.cyTopHeight; + rcClient.right -= ContentMargin.cxRightWidth; + rcClient.bottom -= ContentMargin.cyBottomHeight; + + CONST UINT swpFlags = SWP_DRAWFRAME | SWP_NOCOPYBITS | SWP_NOZORDER; + + if (g_TaskbarSettings.bShowDesktopButton) + { + POINT ptShowDesktop = + { + rcClient.left, + rcClient.top + }; + SIZE showDesktopSize = + { + rcClient.right - rcClient.left, + rcClient.bottom - rcClient.top + }; + + INT cxyShowDesktop = m_ShowDesktopButton.WidthOrHeight(); if (IsHorizontal) { - ptClock.x = pszClient->cx - szTrayClockMin.cx - ContentMargin.cxRightWidth; - ptClock.y = ContentMargin.cyTopHeight; - szClock.cx = szTrayClockMin.cx; - szClock.cy = pszClient->cy - ContentMargin.cyTopHeight - ContentMargin.cyBottomHeight; + if (!TrayTheme) + { + ptShowDesktop.y -= ContentMargin.cyTopHeight; + showDesktopSize.cy += ContentMargin.cyTopHeight + ContentMargin.cyBottomHeight; + } + + rcClient.right -= (cxyShowDesktop - ContentMargin.cxRightWidth); + + ptShowDesktop.x = rcClient.right; + showDesktopSize.cx = cxyShowDesktop; + + // HACK: Clock has layout problems - remove this once addressed. + rcClient.right -= CLOCK_TEXT_HACK; } else { - ptClock.x = ContentMargin.cxLeftWidth; - ptClock.y = pszClient->cy - szTrayClockMin.cy; - szClock.cx = pszClient->cx - ContentMargin.cxLeftWidth - ContentMargin.cxRightWidth; - szClock.cy = szTrayClockMin.cy; + if (!TrayTheme) + { + ptShowDesktop.x -= ContentMargin.cxLeftWidth; + showDesktopSize.cx += ContentMargin.cxLeftWidth + ContentMargin.cxRightWidth; + } + + rcClient.bottom -= (cxyShowDesktop - ContentMargin.cyBottomHeight); + + ptShowDesktop.y = rcClient.bottom; + showDesktopSize.cy = cxyShowDesktop; + + // HACK: Clock has layout problems - remove this once addressed. + rcClient.bottom -= CLOCK_TEXT_HACK; + } + + /* Resize and reposition the button */ + ::SetWindowPos(m_hwndShowDesktop, + NULL, + ptShowDesktop.x, + ptShowDesktop.y, + showDesktopSize.cx, + showDesktopSize.cy, + swpFlags); + } + + if (!g_TaskbarSettings.sr.HideClock) + { + POINT ptClock = { rcClient.left, rcClient.top }; + SIZE clockSize = { rcClient.right - rcClient.left, rcClient.bottom - rcClient.top }; + + if (IsHorizontal) + { + rcClient.right -= trayClockMinSize.cx; + + ptClock.x = rcClient.right; + clockSize.cx = trayClockMinSize.cx; + } + else + { + rcClient.bottom -= trayClockMinSize.cy; + + ptClock.y = rcClient.bottom; + clockSize.cy = trayClockMinSize.cy; } ::SetWindowPos(m_hwndClock, NULL, ptClock.x, ptClock.y, - szClock.cx, - szClock.cy, - SWP_NOZORDER); + clockSize.cx, + clockSize.cy, + swpFlags); } POINT ptPager; - if (IsHorizontal) { ptPager.x = ContentMargin.cxLeftWidth; - ptPager.y = (pszClient->cy - szTrayNotify.cy)/2; + ptPager.y = ((rcClient.bottom - rcClient.top) - trayNotifySize.cy) / 2; + if (g_TaskbarSettings.UseCompactTrayIcons()) + ptPager.y += ContentMargin.cyTopHeight; } else { - ptPager.x = (pszClient->cx - szTrayNotify.cx)/2; + ptPager.x = ((rcClient.right - rcClient.left) - trayNotifySize.cx) / 2; + if (g_TaskbarSettings.UseCompactTrayIcons()) + ptPager.x += ContentMargin.cxLeftWidth; ptPager.y = ContentMargin.cyTopHeight; } @@ -237,9 +352,17 @@ public: NULL, ptPager.x, ptPager.y, - szTrayNotify.cx, - szTrayNotify.cy, - SWP_NOZORDER); + trayNotifySize.cx, + trayNotifySize.cy, + swpFlags); + + if (prcClient != NULL) + { + prcClient->left = rcClient.left - ContentMargin.cxLeftWidth; + prcClient->top = rcClient.top - ContentMargin.cyTopHeight; + prcClient->right = rcClient.right + ContentMargin.cxRightWidth; + prcClient->bottom = rcClient.bottom + ContentMargin.cyBottomHeight; + } } LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) @@ -267,34 +390,68 @@ public: BOOL Horizontal = (BOOL) wParam; if (Horizontal != IsHorizontal) - { IsHorizontal = Horizontal; - if (IsHorizontal) - SetWindowTheme(m_hWnd, L"TrayNotifyHoriz", NULL); - else - SetWindowTheme(m_hWnd, L"TrayNotifyVert", NULL); + + SetWindowTheme(m_hWnd, + IsHorizontal ? L"TrayNotifyHoriz" : L"TrayNotifyVert", + NULL); + m_ShowDesktopButton.m_bHorizontal = Horizontal; + + return (LRESULT)GetMinimumSize((PSIZE)lParam); + } + + LRESULT OnGetShowDesktopButton(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + if (wParam == NULL) + return 0; + + CTrayShowDesktopButton** ptr = (CTrayShowDesktopButton**)wParam; + if (!m_ShowDesktopButton) + { + *ptr = NULL; + return 0; } - return (LRESULT) GetMinimumSize((PSIZE) lParam); + *ptr = &m_ShowDesktopButton; + bHandled = TRUE; + return 0; } LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { - SIZE szClient; + SIZE clientSize; - szClient.cx = LOWORD(lParam); - szClient.cy = HIWORD(lParam); + clientSize.cx = LOWORD(lParam); + clientSize.cy = HIWORD(lParam); - Size(&szClient); + Size(&clientSize); return TRUE; } LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { + POINT pt; + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + + if (m_ShowDesktopButton && m_ShowDesktopButton.PtInButton(&pt)) + return HTCLIENT; + return HTTRANSPARENT; } + LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + POINT pt; + ::GetCursorPos(&pt); + + if (m_ShowDesktopButton && m_ShowDesktopButton.PtInButton(&pt)) + m_ShowDesktopButton.StartHovering(); + + return TRUE; + } + LRESULT OnCtxMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { bHandled = TRUE; @@ -310,6 +467,24 @@ public: return SendMessageW(m_hwndClock, uMsg, wParam, lParam); } + LRESULT OnTaskbarSettingsChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + TaskbarSettings* newSettings = (TaskbarSettings*)lParam; + + /* Toggle show desktop button */ + if (newSettings->bShowDesktopButton != g_TaskbarSettings.bShowDesktopButton) + { + g_TaskbarSettings.bShowDesktopButton = newSettings->bShowDesktopButton; + ::ShowWindow(m_hwndShowDesktop, g_TaskbarSettings.bShowDesktopButton ? SW_SHOW : SW_HIDE); + + /* Ask the parent to resize */ + NMHDR nmh = {m_hWnd, 0, NTNWM_REALIGN}; + SendMessage(WM_NOTIFY, 0, (LPARAM) &nmh); + } + + return OnClockMessage(uMsg, wParam, lParam, bHandled); + } + LRESULT OnPagerMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { return SendMessageW(m_hwndPager, uMsg, wParam, lParam); @@ -334,6 +509,13 @@ public: return E_NOTIMPL; } + HRESULT Initialize(IN HWND hwndParent) + { + const DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + Create(hwndParent, 0, NULL, dwStyle, WS_EX_STATICEDGE); + return m_hWnd ? S_OK : E_FAIL; + } + DECLARE_NOT_AGGREGATABLE(CTrayNotifyWnd) DECLARE_PROTECT_FINAL_CONSTRUCT() @@ -349,24 +531,18 @@ public: MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) MESSAGE_HANDLER(WM_SIZE, OnSize) MESSAGE_HANDLER(WM_NCHITTEST, OnNcHitTest) + MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) + MESSAGE_HANDLER(WM_NCMOUSEMOVE, OnMouseMove) MESSAGE_HANDLER(WM_CONTEXTMENU, OnCtxMenu) MESSAGE_HANDLER(WM_NCLBUTTONDBLCLK, OnClockMessage) - MESSAGE_HANDLER(TWM_SETTINGSCHANGED, OnClockMessage) MESSAGE_HANDLER(WM_SETFONT, OnClockMessage) MESSAGE_HANDLER(WM_SETTINGCHANGE, OnPagerMessage) MESSAGE_HANDLER(WM_COPYDATA, OnPagerMessage) + MESSAGE_HANDLER(TWM_SETTINGSCHANGED, OnTaskbarSettingsChanged) NOTIFY_CODE_HANDLER(NTNWM_REALIGN, OnRealign) MESSAGE_HANDLER(TNWM_GETMINIMUMSIZE, OnGetMinimumSize) + MESSAGE_HANDLER(TNWM_GETSHOWDESKTOPBUTTON, OnGetShowDesktopButton) END_MSG_MAP() - - HRESULT Initialize(IN HWND hwndParent) - { - DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; - Create(hwndParent, 0, NULL, dwStyle, WS_EX_STATICEDGE); - if (!m_hWnd) - return E_FAIL; - return S_OK; - } }; HRESULT CTrayNotifyWnd_CreateInstance(HWND hwndParent, REFIID riid, void **ppv) diff --git a/base/shell/explorer/traywnd.cpp b/base/shell/explorer/traywnd.cpp index 21420cd7ddc..a2d49f8010d 100644 --- a/base/shell/explorer/traywnd.cpp +++ b/base/shell/explorer/traywnd.cpp @@ -319,202 +319,6 @@ public: }; -// This window class name is CONFIRMED on Win10 by WinHier. -static const WCHAR szTrayShowDesktopButton[] = L"TrayShowDesktopButtonWClass"; - -// The 'Show Desktop' button at edge of taskbar -class CTrayShowDesktopButton : - public CWindowImpl -{ - LONG m_nClickedTime; - BOOL m_bHovering; - HTHEME m_hTheme; - -public: - DECLARE_WND_CLASS_EX(szTrayShowDesktopButton, CS_HREDRAW | CS_VREDRAW, COLOR_3DFACE) - - CTrayShowDesktopButton() : m_nClickedTime(0), m_bHovering(FALSE) - { - } - - INT WidthOrHeight() const - { -#define SHOW_DESKTOP_MINIMUM_WIDTH 3 - INT cxy = 2 * ::GetSystemMetrics(SM_CXEDGE); - return max(cxy, SHOW_DESKTOP_MINIMUM_WIDTH); - } - - HRESULT DoCreate(HWND hwndParent) - { - DWORD style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS; - Create(hwndParent, NULL, NULL, style); - if (!m_hWnd) - return E_FAIL; - - ::SetWindowTheme(m_hWnd, L"TaskBar", NULL); - return S_OK; - } - - LRESULT OnClick(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - // The actual action can be delayed as an expected behaviour. - // But a too late action is an unexpected behaviour. - LONG nTime0 = m_nClickedTime; - LONG nTime1 = ::GetMessageTime(); - if (nTime1 - nTime0 >= 600) // Ignore after 0.6 sec - return 0; - - // Show/Hide Desktop - GetParent().SendMessage(WM_COMMAND, TRAYCMD_TOGGLE_DESKTOP, 0); - return 0; - } - -#define TSDB_CLICK (WM_USER + 100) - - // This function is called from OnLButtonDown and parent. - VOID Click() - { - // The actual action can be delayed as an expected behaviour. - m_nClickedTime = ::GetMessageTime(); - PostMessage(TSDB_CLICK, 0, 0); - } - - LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - Click(); // Left-click - return 0; - } - - LRESULT OnSettingChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - if (m_hTheme) - ::CloseThemeData(m_hTheme); - - m_hTheme = ::OpenThemeData(m_hWnd, L"TaskBar"); - InvalidateRect(NULL, TRUE); - return 0; - } - - // This function is called from OnPaint and parent. - VOID OnDraw(HDC hdc, LPRECT prc); - - LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - RECT rc; - GetClientRect(&rc); - - PAINTSTRUCT ps; - HDC hdc = BeginPaint(&ps); - OnDraw(hdc, &rc); - EndPaint(&ps); - return 0; - } - - BOOL PtInButton(POINT pt) - { - if (!IsWindow()) - return FALSE; - RECT rc; - GetWindowRect(&rc); - INT cxEdge = ::GetSystemMetrics(SM_CXEDGE), cyEdge = ::GetSystemMetrics(SM_CYEDGE); - ::InflateRect(&rc, max(cxEdge, 1), max(cyEdge, 1)); - return ::PtInRect(&rc, pt); - } - -#define SHOW_DESKTOP_TIMER_ID 999 -#define SHOW_DESKTOP_TIMER_INTERVAL 200 - - VOID StartHovering() - { - if (m_bHovering) - return; - - m_bHovering = TRUE; - SetTimer(SHOW_DESKTOP_TIMER_ID, SHOW_DESKTOP_TIMER_INTERVAL, NULL); - InvalidateRect(NULL, TRUE); - GetParent().PostMessage(WM_NCPAINT, 0, 0); - } - - LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - StartHovering(); - return 0; - } - - LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - if (wParam != SHOW_DESKTOP_TIMER_ID || !m_bHovering) - return 0; - - POINT pt; - ::GetCursorPos(&pt); - if (!PtInButton(pt)) // The end of hovering? - { - m_bHovering = FALSE; - KillTimer(SHOW_DESKTOP_TIMER_ID); - InvalidateRect(NULL, TRUE); - GetParent().PostMessage(WM_NCPAINT, 0, 0); - } - - return 0; - } - - LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) - { - if (m_hTheme) - { - CloseThemeData(m_hTheme); - m_hTheme = NULL; - } - return 0; - } - - BEGIN_MSG_MAP(CTrayShowDesktopButton) - MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) - MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChanged) - MESSAGE_HANDLER(WM_THEMECHANGED, OnSettingChanged) - MESSAGE_HANDLER(WM_PAINT, OnPaint) - MESSAGE_HANDLER(WM_TIMER, OnTimer) - MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) - MESSAGE_HANDLER(WM_DESTROY, OnDestroy) - MESSAGE_HANDLER(TSDB_CLICK, OnClick) - END_MSG_MAP() -}; - -VOID CTrayShowDesktopButton::OnDraw(HDC hdc, LPRECT prc) -{ - if (m_hTheme) - { - if (m_bHovering) // Draw a hot button - { - HTHEME hButtonTheme = ::OpenThemeData(m_hWnd, L"Button"); - ::DrawThemeBackground(hButtonTheme, hdc, BP_PUSHBUTTON, PBS_NORMAL, prc, prc); - ::CloseThemeData(hButtonTheme); - } - else // Draw a taskbar background - { - ::DrawThemeBackground(m_hTheme, hdc, TBP_BACKGROUNDTOP, 0, prc, prc); - } - } - else - { - RECT rc = *prc; - if (m_bHovering) // Draw a hot button - { - ::DrawFrameControl(hdc, &rc, DFC_BUTTON, DFCS_BUTTONPUSH | DFCS_ADJUSTRECT); - HBRUSH hbrHot = ::CreateSolidBrush(RGB(255, 255, 191)); - ::FillRect(hdc, &rc, hbrHot); - ::DeleteObject(hbrHot); - } - else // Draw a flattish button - { - ::DrawFrameControl(hdc, &rc, DFC_BUTTON, DFCS_BUTTONPUSH); - ::InflateRect(&rc, -1, -1); - ::FillRect(hdc, &rc, ::GetSysColorBrush(COLOR_3DFACE)); - } - } -} - class CTrayWindow : public CComCoClass, public CComObjectRootEx, @@ -525,7 +329,7 @@ class CTrayWindow : public IContextMenu { CStartButton m_StartButton; - CTrayShowDesktopButton m_ShowDesktopButton; + CTrayShowDesktopButton* m_pShowDesktopButton; CComPtr m_StartMenuBand; CComPtr m_StartMenuPopup; @@ -580,7 +384,7 @@ public: public: CTrayWindow() : m_StartButton(), - m_ShowDesktopButton(), + m_pShowDesktopButton(NULL), m_Theme(NULL), m_Font(NULL), m_DesktopWnd(NULL), @@ -1800,6 +1604,7 @@ ChangePos: SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE); ResizeWorkArea(); ApplyClipping(TRUE); + RedrawWindow(NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INTERNALPAINT | RDW_INVALIDATE | RDW_ALLCHILDREN); } VOID RegLoadSettings() @@ -1944,35 +1749,6 @@ ChangePos: } } - if (m_ShowDesktopButton.m_hWnd) - { - // Get rectangle from rcClient - RECT rc = rcClient; - INT cxyShowDesktop = m_ShowDesktopButton.WidthOrHeight(); - if (Horizontal) - { - rc.left = rc.right - cxyShowDesktop; - rc.right += 5; // excessive - } - else - { - rc.top = rc.bottom - cxyShowDesktop; - rc.bottom += 5; // excessive - } - - /* Resize and reposition the button */ - dwp = m_ShowDesktopButton.DeferWindowPos(dwp, NULL, - rc.left, rc.top, - rc.right - rc.left, rc.bottom - rc.top, - SWP_NOZORDER | SWP_NOACTIVATE); - - // Adjust rcClient - if (Horizontal) - rcClient.right -= cxyShowDesktop + ::GetSystemMetrics(SM_CXEDGE); - else - rcClient.bottom -= cxyShowDesktop + ::GetSystemMetrics(SM_CYEDGE); - } - /* Determine the size that the tray notification window needs */ if (Horizontal) { @@ -2558,10 +2334,6 @@ ChangePos: /* Create the Start button */ m_StartButton.Create(m_hWnd); - /* Create the 'Show Desktop' button if necessary */ - if (g_TaskbarSettings.bShowDesktopButton) - m_ShowDesktopButton.DoCreate(m_hWnd); - /* Load the saved tray window settings */ RegLoadSettings(); @@ -2600,6 +2372,10 @@ ChangePos: if (FAILED_UNEXPECTEDLY(hRet)) return FALSE; + ::SendMessage(m_TrayNotify, TNWM_GETSHOWDESKTOPBUTTON, (WPARAM)&m_pShowDesktopButton, 0); + if (!m_pShowDesktopButton) + return FALSE; + SetWindowTheme(m_Rebar, L"TaskBar", NULL); UpdateFonts(); @@ -2739,17 +2515,9 @@ ChangePos: // We have to draw non-client area because the 'Show Desktop' button is beyond client area. void DrawShowDesktopButton() { - if (!m_ShowDesktopButton.IsWindow()) + if (!m_pShowDesktopButton || !m_pShowDesktopButton->IsWindow()) return; - // Get the rectangle in window coordinates - RECT rcButton, rcWnd; - GetWindowRect(&rcWnd); - m_ShowDesktopButton.GetWindowRect(&rcButton); - ::OffsetRect(&rcButton, -rcWnd.left, -rcWnd.top); - - HDC hdc = GetDCEx(NULL, DCX_WINDOW | DCX_CACHE); - m_ShowDesktopButton.OnDraw(hdc, &rcButton); // Draw the button - ReleaseDC(hdc); + ::RedrawWindow(m_TrayNotify, NULL, NULL, RDW_INVALIDATE | RDW_ERASENOW | RDW_UPDATENOW); } LRESULT OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) @@ -2791,8 +2559,11 @@ ChangePos: if (GetClientRect(&rcClient) && (MapWindowPoints(NULL, (LPPOINT) &rcClient, 2) != 0 || GetLastError() == ERROR_SUCCESS)) { - pt.x = (SHORT) LOWORD(lParam); - pt.y = (SHORT) HIWORD(lParam); + pt.x = GET_X_LPARAM(lParam); + pt.y = GET_Y_LPARAM(lParam); + + if (m_pShowDesktopButton && ::IsWindow(m_pShowDesktopButton->m_hWnd) && m_pShowDesktopButton->PtInButton(&pt)) + return HTBORDER; if (PtInRect(&rcClient, pt)) { @@ -2983,11 +2754,75 @@ ChangePos: return TRUE; } + BOOL IsPointWithinStartButton(LPPOINT ppt, LPRECT prcStartBtn, PWINDOWINFO pwi) + { + if (!ppt || !prcStartBtn || !pwi) + return FALSE; + + switch (m_Position) + { + case ABE_TOP: + case ABE_LEFT: + { + if (ppt->x > prcStartBtn->right || ppt->y > prcStartBtn->bottom) + return FALSE; + break; + } + case ABE_RIGHT: + { + if (ppt->x < prcStartBtn->left || ppt->y > prcStartBtn->bottom) + return FALSE; + + if (prcStartBtn->right + (int)pwi->cxWindowBorders * 2 + 1 < pwi->rcWindow.right && + ppt->x > prcStartBtn->right) + { + return FALSE; + } + break; + } + case ABE_BOTTOM: + { + if (ppt->x > prcStartBtn->right || ppt->y < prcStartBtn->top) + return FALSE; + + if (prcStartBtn->bottom + (int)pwi->cyWindowBorders * 2 + 1 < pwi->rcWindow.bottom && + ppt->y > prcStartBtn->bottom) + { + return FALSE; + } + + break; + } + } + return TRUE; + } + + BOOL IsPointWithinShowDesktopButton(LPPOINT ppt, LPRECT prcShowDesktopBtn, PWINDOWINFO pwi) + { + if (!ppt || !prcShowDesktopBtn) + return FALSE; + UNREFERENCED_PARAMETER(pwi); + + switch (m_Position) + { + case ABE_LEFT: + return !(ppt->x > prcShowDesktopBtn->right || ppt->y < prcShowDesktopBtn->top); + case ABE_TOP: + return !(ppt->x < prcShowDesktopBtn->left || ppt->y > prcShowDesktopBtn->bottom); + case ABE_RIGHT: + return !(ppt->x < prcShowDesktopBtn->left || ppt->y < prcShowDesktopBtn->top); + case ABE_BOTTOM: + return !(ppt->x < prcShowDesktopBtn->left || ppt->y < prcShowDesktopBtn->top); + } + return FALSE; + } + + /** + * This handler implements the trick that makes the start button to + * get pressed when the user clicked left or below the button. + */ LRESULT OnNcLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { - /* This handler implements the trick that makes the start button to - get pressed when the user clicked left or below the button */ - POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; WINDOWINFO wi = {sizeof(WINDOWINFO)}; @@ -2995,47 +2830,18 @@ ChangePos: RECT rcStartBtn; m_StartButton.GetWindowRect(&rcStartBtn); - GetWindowInfo(m_hWnd, &wi); - switch (m_Position) + if (IsPointWithinStartButton(&pt, &rcStartBtn, &wi)) { - case ABE_TOP: - case ABE_LEFT: - { - if (pt.x > rcStartBtn.right || pt.y > rcStartBtn.bottom) - return 0; - break; - } - case ABE_RIGHT: - { - if (pt.x < rcStartBtn.left || pt.y > rcStartBtn.bottom) - return 0; - - if (rcStartBtn.right + (int)wi.cxWindowBorders * 2 + 1 < wi.rcWindow.right && - pt.x > rcStartBtn.right) - { - return 0; - } - break; - } - case ABE_BOTTOM: - { - if (pt.x > rcStartBtn.right || pt.y < rcStartBtn.top) - return 0; - - if (rcStartBtn.bottom + (int)wi.cyWindowBorders * 2 + 1 < wi.rcWindow.bottom && - pt.y > rcStartBtn.bottom) - { - return 0; - } - - break; - } + bHandled = TRUE; + PopupStartMenu(); + return 0; } - bHandled = TRUE; - PopupStartMenu(); + if (m_pShowDesktopButton && m_pShowDesktopButton->PtInButton(&pt)) + m_pShowDesktopButton->OnLButtonDown(WM_LBUTTONDOWN, 0, 0, bHandled); + return 0; } @@ -3151,19 +2957,6 @@ HandleTrayContextMenu: return Ret; } - BOOL CheckShowDesktopButtonClick(LPARAM lParam, BOOL& bHandled) - { - POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; - if (m_ShowDesktopButton.PtInButton(pt)) // Did you click the button? - { - m_ShowDesktopButton.Click(); - bHandled = TRUE; - return TRUE; - } - - return FALSE; - } - LRESULT OnNcLButtonDblClick(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { /* Let the clock handle the double-click */ @@ -3176,7 +2969,20 @@ HandleTrayContextMenu: LRESULT OnNcLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { - CheckShowDesktopButtonClick(lParam, bHandled); + if (m_pShowDesktopButton && m_pShowDesktopButton->m_bPressed) // Did you click the button? + { + m_pShowDesktopButton->Click(); + m_pShowDesktopButton->OnLButtonUp(WM_LBUTTONUP, 0, 0, bHandled); + bHandled = TRUE; + } + + return FALSE; + } + + LRESULT OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) + { + if (m_pShowDesktopButton) + m_pShowDesktopButton->OnLButtonUp(uMsg, wParam, lParam, bHandled); return FALSE; } @@ -3367,10 +3173,7 @@ HandleTrayContextMenu: LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { - POINT pt; - ::GetCursorPos(&pt); - if (m_ShowDesktopButton.PtInButton(pt)) - m_ShowDesktopButton.StartHovering(); + SendMessage(m_TrayNotify, uMsg, wParam, lParam); if (g_TaskbarSettings.sr.AutoHide) { @@ -3553,17 +3356,6 @@ HandleTrayContextMenu: SetWindowPos(hWndInsertAfter, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); } - /* Toggle show desktop button */ - if (newSettings->bShowDesktopButton != g_TaskbarSettings.bShowDesktopButton) - { - g_TaskbarSettings.bShowDesktopButton = newSettings->bShowDesktopButton; - if (!g_TaskbarSettings.bShowDesktopButton) - ::DestroyWindow(m_ShowDesktopButton.m_hWnd); - else if (!m_ShowDesktopButton.IsWindow()) - m_ShowDesktopButton.DoCreate(m_hWnd); - AlignControls(NULL); - } - /* Adjust taskbar size */ CheckTrayWndPosition(); @@ -3620,6 +3412,7 @@ HandleTrayContextMenu: MESSAGE_HANDLER(WM_SYSCHAR, OnSysChar) MESSAGE_HANDLER(WM_NCRBUTTONUP, OnNcRButtonUp) MESSAGE_HANDLER(WM_NCLBUTTONDBLCLK, OnNcLButtonDblClick) + MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp) MESSAGE_HANDLER(WM_NCLBUTTONUP, OnNcLButtonUp) MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove) MESSAGE_HANDLER(WM_NCMOUSEMOVE, OnMouseMove)