Skip to content

Commit

Permalink
Title bar background color and text color follow windows settings whe…
Browse files Browse the repository at this point in the history
…n not customized (#2505) (2)

-  Use accent color as titlebar color only if "Show accent color in title bars and window borders" is set to "On" in the Windows Settings > Personalization > Colors page.

-  For Windows XP support, I would like to avoid using DwmGetColorizationColor(). I would like to get accent color from registry.

-  WinMerge originally used COLOR_ACTIVECAPTION and COLOR_INACTIVECAPTION, but I don't want to use them as titlebar color because they are documented as unsupported in Windows 10 and later.

-  Move accent color related handling from CMDITabBar to CTitleBarHelper.
  • Loading branch information
sdottaka committed Nov 16, 2024
1 parent acf4b6d commit 44f94c0
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 77 deletions.
39 changes: 39 additions & 0 deletions Src/Common/AccentColor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) 2024 Takashi Sawanaka
// SPDX-License-Identifier: BSL-1.0
/**
* @file AccentColor.cpp
*
* @brief Implementation of the CAccentColor class
*/

#include "StdAfx.h"
#include "AccentColor.h"
#include "RegKey.h"

CAccentColor::CAccentColor()
: m_accentColor(CLR_NONE)
, m_accentColorInactive(CLR_NONE)
, m_colorPrevalence(false)
{
Reload();
}

CAccentColor& CAccentColor::Get()
{
static CAccentColor s_accentColor;
return s_accentColor;
}

void CAccentColor::Reload()
{
CRegKeyEx reg;
if (ERROR_SUCCESS != reg.Open(HKEY_CURRENT_USER, _T("SOFTWARE\\Microsoft\\Windows\\DWM")))
return;
m_accentColor = reg.ReadDword(_T("AccentColor"), CLR_NONE);
if (m_accentColor != CLR_NONE)
m_accentColor &= 0xffffff;
m_accentColorInactive = reg.ReadDword(_T("AccentColorInactive"), CLR_NONE);
if (m_accentColorInactive != CLR_NONE)
m_accentColorInactive &= 0xffffff;
m_colorPrevalence = reg.ReadDword(_T("ColorPrevalence"), false);
}
22 changes: 22 additions & 0 deletions Src/Common/AccentColor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) 2024 Takashi Sawanaka
// SPDX-License-Identifier: BSL-1.0
/**
* @file AccentColor.h
*
* @brief Declaration file for CAccentColor class
*/

class CAccentColor
{
public:
CAccentColor();
COLORREF GetAccentColor() const { return m_accentColor; };
COLORREF GetAccentColorInactive() const { return m_accentColorInactive; }
bool GetColorPrevalence() const { return m_colorPrevalence; }
void Reload();
static CAccentColor& Get();
private:
COLORREF m_accentColor;
COLORREF m_accentColorInactive;
bool m_colorPrevalence;
};
72 changes: 10 additions & 62 deletions Src/Common/MDITabBar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@
#include "IMDITab.h"
#include "cecolor.h"
#include "RoundedRectWithShadow.h"
#include <dwmapi.h>
#include <RegKey.h>
#pragma comment(lib, "dwmapi.lib")

#ifdef _DEBUG
#define new DEBUG_NEW
Expand Down Expand Up @@ -72,15 +69,6 @@ BOOL CMyTabCtrl::Create(CMDIFrameWnd* pMainFrame, CWnd* pParent)
m_pMainFrame = pMainFrame;
m_tooltips.Create(m_pMainFrame, TTS_NOPREFIX);
m_tooltips.AddTool(this, _T(""));
CRegKeyEx reg;
constexpr tchar_t* AccentColorInactive = _T("AccentColorInactive");
constexpr tchar_t* RegDir = _T("SOFTWARE\\Microsoft\\Windows\\DWM");
if (ERROR_SUCCESS == reg.Open(HKEY_CURRENT_USER, RegDir))
{
const auto clr = reg.ReadDword(AccentColorInactive, 0);
if (clr)
m_dwInactiveTitleColor = RGB(GetRValue(clr), GetGValue(clr), GetBValue(clr));
}
return TRUE;
}

Expand All @@ -98,67 +86,27 @@ BOOL CMyTabCtrl::PreTranslateMessage(MSG* pMsg)
return __super::PreTranslateMessage(pMsg);
}

COLORREF CMyTabCtrl::GetDwmTitlebarColors()
{
if (!m_bActive)
{
if (m_dwInactiveTitleColor)
return m_dwInactiveTitleColor;
return GetSysColor(COLOR_INACTIVECAPTION);
}
DWORD czclr = 0;
BOOL opaqueBlend = FALSE;
HRESULT hr = DwmGetColorizationColor(&czclr, &opaqueBlend);
if (SUCCEEDED(hr))
{
return RGB(static_cast<BYTE>(czclr >> 16), static_cast<BYTE>(czclr >> 8), static_cast<BYTE>(czclr));
}
return GetSysColor(COLOR_ACTIVECAPTION);
}

COLORREF CMyTabCtrl::GetDwmTitleTextColors()
void CMyTabCtrl::SetActive(bool bActive)
{
if (!m_bActive)
{
COLORREF clr = m_dwInactiveTitleColor ? m_dwInactiveTitleColor : GetSysColor(COLOR_INACTIVECAPTION);
if (GetRValue(clr) < 128 && GetGValue(clr) < 128 && GetBValue(clr) < 128)
return RGB(245, 245, 245);
return RGB(10, 10, 10);
}
DWORD czclr = 0;
BOOL opaqueBlend = FALSE;
HRESULT hr = DwmGetColorizationColor(&czclr, &opaqueBlend);
if (SUCCEEDED(hr))
{
const BYTE r = static_cast<BYTE>(czclr >> 16);
const BYTE g = static_cast<BYTE>(czclr >> 8);
const BYTE b = static_cast<BYTE>(czclr);
if (r < 128 && g < 128 && b < 128)
return RGB(255, 255, 255);
return RGB(0, 0, 0);
}
return GetSysColor(COLOR_CAPTIONTEXT);
CTitleBarHelper::ReloadAccentColor();
m_bActive = bActive;
}

static inline COLORREF getTextColor()
{
return GetSysColor(COLOR_WINDOWTEXT);
}

COLORREF CMyTabCtrl::GetBackColor()
COLORREF CMyTabCtrl::GetBackColor() const
{
const COLORREF clr = GetSysColor(COLOR_3DFACE);
if (!m_bOnTitleBar)
return clr;
if (!m_bCustomSystemColor)
return GetDwmTitlebarColors();
const COLORREF bgclr = m_bActive ?
RGB(GetRValue(clr), std::clamp(GetGValue(clr) + 8, 0, 255), std::clamp(GetBValue(clr) + 8, 0, 255))
: clr;
return bgclr;
return CTitleBarHelper::GetBackColor(m_bActive);
}

static inline bool IsHighContrastEnabled()

{
HIGHCONTRAST hc = { sizeof(HIGHCONTRAST) };
SystemParametersInfo(SPI_GETHIGHCONTRAST, sizeof(hc), &hc, 0);
Expand All @@ -179,8 +127,8 @@ void CMyTabCtrl::OnPaint()
const int nCount = GetItemCount();
if (nCount == 0)
{
const COLORREF winTitleTextColor = (m_bOnTitleBar && !m_bCustomSystemColor) ?
GetDwmTitleTextColors() : GetSysColor(COLOR_WINDOWTEXT);
const COLORREF winTitleTextColor = m_bOnTitleBar ?
CTitleBarHelper::GetTextColor(m_bActive) : getTextColor();
dc.SetTextColor(winTitleTextColor);
TCHAR szBuf[256];
AfxGetMainWnd()->GetWindowText(szBuf, sizeof(szBuf) / sizeof(szBuf[0]));
Expand Down Expand Up @@ -445,8 +393,8 @@ void CMyTabCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
}
else
{
const COLORREF txtclr = (m_bOnTitleBar && !m_bCustomSystemColor) ?
GetDwmTitleTextColors() : GetSysColor(COLOR_BTNTEXT);
const COLORREF txtclr = m_bOnTitleBar ?
CTitleBarHelper::GetTextColor(m_bActive) : GetSysColor(COLOR_BTNTEXT);
SetTextColor(lpDraw->hDC, txtclr);
}
CSize iconsize(determineIconSize(), determineIconSize());
Expand Down
14 changes: 4 additions & 10 deletions Src/Common/MDITabBar.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ class CMyTabCtrl : public CTabCtrl
, m_nTooltipTabItemIndex(-1)
, m_bOnTitleBar(false)
, m_bActive(false)
, m_dwInactiveTitleColor(0)
{}

protected:
Expand All @@ -34,13 +33,11 @@ class CMyTabCtrl : public CTabCtrl
bool m_bCloseButtonDown;
bool m_bOnTitleBar;
bool m_bActive;
bool m_bCustomSystemColor;
CRect m_rcCurrentCloseButtom;
int m_nDraggingTabItemIndex;
int m_nTooltipTabItemIndex; /**< Index of the tab displaying tooltip */
CMDIFrameWnd *m_pMainFrame;
CToolTipCtrl m_tooltips; /**< Tooltip for the tab */
COLORREF m_dwInactiveTitleColor;

public:
BOOL Create(CMDIFrameWnd* pMainFrame, CWnd* pParent);
Expand All @@ -49,10 +46,8 @@ class CMyTabCtrl : public CTabCtrl
void UpdateTabs();
void SetOnTitleBar(bool onTitleBar) { m_bOnTitleBar = onTitleBar; }
bool GetActive() const { return m_bActive; }
void SetActive(bool bActive) { m_bActive = bActive; }
COLORREF GetBackColor();
bool GetCustomSystemColor() const { return m_bCustomSystemColor; }
void SetCustomSystemColor(bool bCustom) { m_bCustomSystemColor = bCustom; }
void SetActive(bool bActive);
COLORREF GetBackColor() const;

// Overrides
// ClassWizard generated virtual function overrides
Expand Down Expand Up @@ -86,8 +81,8 @@ class CMyTabCtrl : public CTabCtrl
void SwapTabs(int nIndexA, int nIndexB);
int GetMaxTitleLength() const;
void UpdateToolTips(int index);
COLORREF GetDwmTitleTextColors();
COLORREF GetDwmTitlebarColors();
COLORREF GetDwmTitleTextColor() const;
COLORREF GetDwmTitlebarColor() const;
};

/**
Expand All @@ -111,7 +106,6 @@ class CMDITabBar : public CControlBar
virtual ~CMDITabBar() {}
BOOL Update(bool bOnTitleBar, bool bMaxmized);
void UpdateActive(bool bActive);
void UpdateCustomSystemColor(bool bCustom) { m_tabCtrl.SetCustomSystemColor(bCustom); };
BOOL Create(CMDIFrameWnd* pParentWnd);
void UpdateTabs() { m_tabCtrl.UpdateTabs(); }
bool GetAutoMaxWidth() const { return m_tabCtrl.GetAutoMaxWidth(); }
Expand Down
11 changes: 6 additions & 5 deletions Src/MainFrm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@
#include "DirWatcher.h"
#include "Win_VersionHelper.h"

#if !defined(SM_CXPADDEDBORDER)
#define SM_CXPADDEDBORDER 92
#endif

using std::vector;
using boost::begin;
using boost::end;
Expand Down Expand Up @@ -416,7 +420,6 @@ int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
m_bTabsOnTitleBar = GetOptionsMgr()->GetBool(OPT_TABBAR_ON_TITLEBAR);

m_wndTabBar.Update(m_bTabsOnTitleBar.value_or(false), false);
m_wndTabBar.UpdateCustomSystemColor(GetOptionsMgr()->GetBool(OPT_SYSCOLOR_HOOK_ENABLED));

if (m_bTabsOnTitleBar.value_or(false) && !m_wndTabBar.Create(this))
{
Expand Down Expand Up @@ -1235,11 +1238,9 @@ void CMainFrame::OnOptions()
for (auto pImgMergeFrame : GetAllImgMergeFrames())
pImgMergeFrame->RefreshOptions();

const bool optSysColorHookEnabled = GetOptionsMgr()->GetBool(OPT_SYSCOLOR_HOOK_ENABLED);
if (sysColorHookEnabled != optSysColorHookEnabled ||
sysColorsSerialized != GetOptionsMgr()->GetString(OPT_SYSCOLOR_HOOK_COLORS))
if (sysColorHookEnabled != GetOptionsMgr()->GetBool(OPT_SYSCOLOR_HOOK_ENABLED) ||
sysColorsSerialized != GetOptionsMgr()->GetString(OPT_SYSCOLOR_HOOK_COLORS))
{
m_wndTabBar.UpdateCustomSystemColor(optSysColorHookEnabled);
theApp.ReloadCustomSysColors();
AfxGetMainWnd()->SendMessage(WM_SYSCOLORCHANGE);
RedrawWindow(nullptr, nullptr, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_ALLCHILDREN);
Expand Down
2 changes: 2 additions & 0 deletions Src/Merge.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,7 @@
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>$(IntDir)$(TargetName)2.pch</PrecompiledHeaderOutputFile>
</ClCompile>
<ClCompile Include="Common\AccentColor.cpp" />
<ClCompile Include="Common\cio.cpp">
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>$(IntDir)$(TargetName)2.pch</PrecompiledHeaderOutputFile>
Expand Down Expand Up @@ -1456,6 +1457,7 @@
<ClInclude Include="BasicFlatStatusBar.h" />
<ClInclude Include="ClipboardHistory.h" />
<ClInclude Include="ColorSchemes.h" />
<ClInclude Include="Common\AccentColor.h" />
<ClInclude Include="Common\SysColorHook.h" />
<ClInclude Include="MouseHook.h" />
<ClInclude Include="MenuBar.h" />
Expand Down
6 changes: 6 additions & 0 deletions Src/Merge.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,9 @@
<ClCompile Include="ColorSchemes.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Common\AccentColor.cpp">
<Filter>MFCGui\Common\Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="charsets.h">
Expand Down Expand Up @@ -1436,6 +1439,9 @@
<ClInclude Include="ColorSchemes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Common\AccentColor.h">
<Filter>MFCGui\Common\Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="res\binarydiff.ico">
Expand Down
46 changes: 46 additions & 0 deletions Src/TitleBarHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "StdAfx.h"
#include "TitleBarHelper.h"
#include "AccentColor.h"

#if !defined(SM_CXPADDEDBORDER)
#define SM_CXPADDEDBORDER 92
Expand Down Expand Up @@ -288,3 +289,48 @@ COLORREF CTitleBarHelper::GetIntermediateColor(COLORREF a, COLORREF b, float rat
const uint8_t B = static_cast<int8_t>((GetBValue(a) - GetBValue(b)) * ratio) + GetBValue(b);
return RGB(R, G, B);
}

COLORREF CTitleBarHelper::GetBackColor(bool bActive)
{
if (!CAccentColor::Get().GetColorPrevalence())
{
const COLORREF clr = GetSysColor(COLOR_3DFACE);
const COLORREF bgclr = bActive ?
RGB(GetRValue(clr), std::clamp(GetGValue(clr) + 8, 0, 255), std::clamp(GetBValue(clr) + 8, 0, 255))
: clr;
return bgclr;
}
const COLORREF czclr = (!bActive) ?
CAccentColor::Get().GetAccentColorInactive() :
CAccentColor::Get().GetAccentColor();
return czclr != CLR_NONE ? czclr : GetSysColor(COLOR_3DFACE);
}

COLORREF CTitleBarHelper::GetTextColor(bool bActive)
{
if (!CAccentColor::Get().GetColorPrevalence())
return GetSysColor(COLOR_BTNTEXT);
if (!bActive)
{
COLORREF clr = GetSysColor(COLOR_3DFACE);
if (GetRValue(clr) < 128 && GetGValue(clr) < 128 && GetBValue(clr) < 128)
return RGB(245, 245, 245);
return RGB(10, 10, 10);
}
const COLORREF czclr = CAccentColor::Get().GetAccentColor();
if (czclr != CLR_NONE)
{
const BYTE r = static_cast<BYTE>(czclr >> 16);
const BYTE g = static_cast<BYTE>(czclr >> 8);
const BYTE b = static_cast<BYTE>(czclr);
if (r < 128 && g < 128 && b < 128)
return RGB(255, 255, 255);
return RGB(0, 0, 0);
}
return GetSysColor(COLOR_BTNTEXT);
}

void CTitleBarHelper::ReloadAccentColor()
{
CAccentColor::Get().Reload();
}
3 changes: 3 additions & 0 deletions Src/TitleBarHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ class CTitleBarHelper {
void SetMaximized(bool maximized) { m_maximized = maximized; }
bool GetMaximized() const { return m_maximized; }
void SetSize(int cx, int cy);
static COLORREF GetBackColor(bool bActive);
static COLORREF GetTextColor(bool bActive);
static void ReloadAccentColor();
LRESULT OnNcHitTest(CPoint pt);
void OnNcMouseMove(UINT nHitTest, CPoint point);
void OnNcMouseLeave();
Expand Down

0 comments on commit 44f94c0

Please sign in to comment.