[EXPLORER] Improve appearance of Show Desktop button (#5744)

While functional, Katayama's show desktop button left much to be desired
in the realm of appearances. This commit brings improvements for it:

- When using the classic theme, the Show Desktop button now appears
  more faithful to its Microsoft counterpart, emblazoned with an icon,
  and encased in a border only when hovered or pressed.
- With a visual style applied, the button behaves in one of two ways:
  - If present, the Show Desktop button now properly uses the relevant
    information from the visual style, just like on Windows 7.
  - Otherwise, the Show Desktop button uses an icon akin to when the
    classic theme is used, but with the button background's appearance
    repurposed from the taskbar toolbar buttons, which are guaranteed to
    exist in any Windows XP or Vista visual style you can find out there.

ReactOS's own Lautus and Mizu visual styles will be updated in the
following commits to utilize these features, while Lunar and Modern visual
styles left untouched to display Show Desktop button with icon instead.

CORE-15369
This commit is contained in:
Ethan Rodensky 2023-09-29 22:16:22 -04:00 committed by Stanislav Motylkov
parent 6910fa624f
commit 70d7009ad9
6 changed files with 810 additions and 379 deletions

View file

@ -22,6 +22,7 @@ list(APPEND SOURCE
taskswnd.cpp
tbsite.cpp
trayclock.cpp
traydeskbtn.cpp
trayntfy.cpp
trayprop.cpp
traywnd.cpp

View file

@ -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
*/

View file

@ -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 <w3seek@reactos.org>
* Copyright 2018-2022 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
* Copyright 2023 Ethan Rodensky <splitwirez@gmail.com>
*/
#include "precomp.h"
#include <commoncontrols.h>
#include <uxtheme.h>
#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);
}
}
}

View file

@ -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 <w3seek@reactos.org>
* Copyright 2018-2022 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
* Copyright 2023 Ethan Rodensky <splitwirez@gmail.com>
*/
#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<CTrayShowDesktopButton, CWindow, CControlWinTraits>
{
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);
};

View file

@ -20,15 +20,17 @@
*/
#include "precomp.h"
/*
* TrayNotifyWnd
*/
#include <commoncontrols.h>
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<CTrayNotifyWnd>,
@ -37,14 +39,17 @@ class CTrayNotifyWnd :
public IOleWindow
{
CComPtr<IUnknown> m_clock;
CTrayShowDesktopButton m_ShowDesktopButton;
CComPtr<IUnknown> 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)

View file

@ -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<CTrayShowDesktopButton, CWindow, CControlWinTraits>
{
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<CTrayWindow>,
public CComObjectRootEx<CComMultiThreadModelNoCS>,
@ -525,7 +329,7 @@ class CTrayWindow :
public IContextMenu
{
CStartButton m_StartButton;
CTrayShowDesktopButton m_ShowDesktopButton;
CTrayShowDesktopButton* m_pShowDesktopButton;
CComPtr<IMenuBand> m_StartMenuBand;
CComPtr<IMenuPopup> 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)