Highlight dark mode combobox border on focus

Fix #11574, close #11575
pull/11610/head
ozone10 2022-04-23 17:10:22 +02:00 committed by Don Ho
parent 2fbac354ed
commit dfc9fb6f3b
4 changed files with 90 additions and 33 deletions

View File

@ -505,6 +505,7 @@ enum Platform { PF_UNKNOWN, PF_X86, PF_X64, PF_IA64, PF_ARM64 };
// COLORREF disabledText = 0;
// COLORREF linkText = 0;
// COLORREF edge = 0;
// COLORREF hotEdge = 0;
// };
// }
//

View File

@ -2635,6 +2635,7 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
currentColors->disabledText = NppDarkMode::getDisabledTextColor();
currentColors->linkText = NppDarkMode::getLinkTextColor();
currentColors->edge = NppDarkMode::getEdgeColor();
currentColors->hotEdge = NppDarkMode::getHotEdgeColor();
return static_cast<LRESULT>(true);
}

View File

@ -47,12 +47,18 @@ namespace NppDarkMode
HBRUSH pureBackground = nullptr;
HBRUSH errorBackground = nullptr;
HBRUSH edgeBrush = nullptr;
HBRUSH hotEdgeBrush = nullptr;
Brushes(const Colors& colors)
: background(::CreateSolidBrush(colors.background))
, softerBackground(::CreateSolidBrush(colors.softerBackground))
, hotBackground(::CreateSolidBrush(colors.hotBackground))
, pureBackground(::CreateSolidBrush(colors.pureBackground))
, errorBackground(::CreateSolidBrush(colors.errorBackground))
, edgeBrush(::CreateSolidBrush(colors.edge))
, hotEdgeBrush(::CreateSolidBrush(colors.hotEdge))
{}
~Brushes()
@ -62,6 +68,9 @@ namespace NppDarkMode
::DeleteObject(hotBackground); hotBackground = nullptr;
::DeleteObject(pureBackground); pureBackground = nullptr;
::DeleteObject(errorBackground); errorBackground = nullptr;
::DeleteObject(edgeBrush); edgeBrush = nullptr;
::DeleteObject(hotEdgeBrush); hotEdgeBrush = nullptr;
}
void change(const Colors& colors)
@ -72,11 +81,17 @@ namespace NppDarkMode
::DeleteObject(pureBackground);
::DeleteObject(errorBackground);
::DeleteObject(edgeBrush);
::DeleteObject(hotEdgeBrush);
background = ::CreateSolidBrush(colors.background);
softerBackground = ::CreateSolidBrush(colors.softerBackground);
hotBackground = ::CreateSolidBrush(colors.hotBackground);
pureBackground = ::CreateSolidBrush(colors.pureBackground);
errorBackground = ::CreateSolidBrush(colors.errorBackground);
edgeBrush = ::CreateSolidBrush(colors.edge);
hotEdgeBrush = ::CreateSolidBrush(colors.hotEdge);
}
};
@ -84,25 +99,30 @@ namespace NppDarkMode
{
HPEN darkerTextPen = nullptr;
HPEN edgePen = nullptr;
HPEN hotEdgePen = nullptr;
Pens(const Colors& colors)
: darkerTextPen(::CreatePen(PS_SOLID, 1, colors.darkerText))
, edgePen(::CreatePen(PS_SOLID, 1, colors.edge))
, hotEdgePen(::CreatePen(PS_SOLID, 1, colors.hotEdge))
{}
~Pens()
{
::DeleteObject(darkerTextPen); darkerTextPen = nullptr;
::DeleteObject(edgePen); edgePen = nullptr;
::DeleteObject(hotEdgePen); hotEdgePen = nullptr;
}
void change(const Colors& colors)
{
::DeleteObject(darkerTextPen);
::DeleteObject(edgePen);
::DeleteObject(hotEdgePen);
darkerTextPen = ::CreatePen(PS_SOLID, 1, colors.darkerText);
edgePen = ::CreatePen(PS_SOLID, 1, colors.edge);
hotEdgePen = ::CreatePen(PS_SOLID, 1, colors.hotEdge);
}
};
@ -118,7 +138,8 @@ namespace NppDarkMode
HEXRGB(0xC0C0C0), // darkerTextColor
HEXRGB(0x808080), // disabledTextColor
HEXRGB(0xFFFF00), // linkTextColor
HEXRGB(0x646464) // edgeColor
HEXRGB(0x646464), // edgeColor
HEXRGB(0x9B9B9B) // hotEdgeColor
};
// red tone
@ -132,7 +153,8 @@ namespace NppDarkMode
HEXRGB(0xC0C0C0), // darkerTextColor
HEXRGB(0x808080), // disabledTextColor
HEXRGB(0xFFFF00), // linkTextColor
HEXRGB(0x908080) // edgeColor
HEXRGB(0x908080), // edgeColor
HEXRGB(0xBBABAB) // hotEdgeColor
};
// green tone
@ -146,7 +168,8 @@ namespace NppDarkMode
HEXRGB(0xC0C0C0), // darkerTextColor
HEXRGB(0x808080), // disabledTextColor
HEXRGB(0xFFFF00), // linkTextColor
HEXRGB(0x809080) // edgeColor
HEXRGB(0x809080), // edgeColor
HEXRGB(0xABBBAB) // hotEdgeColor
};
// blue tone
@ -160,7 +183,8 @@ namespace NppDarkMode
HEXRGB(0xC0C0C0), // darkerTextColor
HEXRGB(0x808080), // disabledTextColor
HEXRGB(0xFFFF00), // linkTextColor
HEXRGB(0x8080A0) // edgeColor
HEXRGB(0x8080A0), // edgeColor
HEXRGB(0xABABCB) // hotEdgeColor
};
// purple tone
@ -174,7 +198,8 @@ namespace NppDarkMode
HEXRGB(0xC0C0C0), // darkerTextColor
HEXRGB(0x808080), // disabledTextColor
HEXRGB(0xFFFF00), // linkTextColor
HEXRGB(0x9080A0) // edgeColor
HEXRGB(0x9080A0), // edgeColor
HEXRGB(0xBBABCB) // hotEdgeColor
};
// cyan tone
@ -188,7 +213,8 @@ namespace NppDarkMode
HEXRGB(0xC0C0C0), // darkerTextColor
HEXRGB(0x808080), // disabledTextColor
HEXRGB(0xFFFF00), // linkTextColor
HEXRGB(0x8090A0) // edgeColor
HEXRGB(0x8090A0), // edgeColor
HEXRGB(0xBBBBCB) // hotEdgeColor
};
// olive tone
@ -202,7 +228,8 @@ namespace NppDarkMode
HEXRGB(0xC0C0C0), // darkerTextColor
HEXRGB(0x808080), // disabledTextColor
HEXRGB(0xFFFF00), // linkTextColor
HEXRGB(0x909080) // edgeColor
HEXRGB(0x909080), // edgeColor
HEXRGB(0xBBBBAB) // hotEdgeColor
};
// customized
@ -216,7 +243,8 @@ namespace NppDarkMode
HEXRGB(0xC0C0C0), // darkerTextColor
HEXRGB(0x808080), // disabledTextColor
HEXRGB(0xFFFF00), // linkTextColor
HEXRGB(0x646464) // edgeColor
HEXRGB(0x646464), // edgeColor
HEXRGB(0x9B9B9B) // hotEdgeColor
};
ColorTone g_colorToneChoice = blackTone;
@ -432,6 +460,7 @@ namespace NppDarkMode
COLORREF getDisabledTextColor() { return getTheme()._colors.disabledText; }
COLORREF getLinkTextColor() { return getTheme()._colors.linkText; }
COLORREF getEdgeColor() { return getTheme()._colors.edge; }
COLORREF getHotEdgeColor() { return getTheme()._colors.hotEdge; }
HBRUSH getBackgroundBrush() { return getTheme()._brushes.background; }
HBRUSH getSofterBackgroundBrush() { return getTheme()._brushes.softerBackground; }
@ -439,8 +468,12 @@ namespace NppDarkMode
HBRUSH getDarkerBackgroundBrush() { return getTheme()._brushes.pureBackground; }
HBRUSH getErrorBackgroundBrush() { return getTheme()._brushes.errorBackground; }
HBRUSH getEdgeBrush() { return getTheme()._brushes.edgeBrush; }
HBRUSH getHotEdgeBrush() { return getTheme()._brushes.hotEdgeBrush; }
HPEN getDarkerTextPen() { return getTheme()._pens.darkerTextPen; }
HPEN getEdgePen() { return getTheme()._pens.edgePen; }
HPEN getHotEdgePen() { return getTheme()._pens.hotEdgePen; }
void setBackgroundColor(COLORREF c)
{
@ -1293,9 +1326,11 @@ namespace NppDarkMode
WPARAM wParam,
LPARAM lParam,
UINT_PTR uIdSubclass,
DWORD_PTR /*dwRefData*/
DWORD_PTR dwRefData
)
{
auto hwndEdit = reinterpret_cast<HWND>(dwRefData);
switch (uMsg)
{
case WM_PAINT:
@ -1308,33 +1343,33 @@ namespace NppDarkMode
RECT rc = {};
::GetClientRect(hWnd, &rc);
PAINTSTRUCT ps;
PAINTSTRUCT ps{};
auto hdc = ::BeginPaint(hWnd, &ps);
auto holdPen = static_cast<HPEN>(::SelectObject(hdc, NppDarkMode::getEdgePen()));
::SelectObject(hdc, reinterpret_cast<HFONT>(::SendMessage(hWnd, WM_GETFONT, 0, 0)));
::SetBkColor(hdc, NppDarkMode::getBackgroundColor());
::SelectObject(hdc, ::GetStockObject(NULL_BRUSH)); // to avoid text flicker, use only border
::Rectangle(hdc, 0, 0, rc.right, rc.bottom);
auto holdBrush = ::SelectObject(hdc, NppDarkMode::getDarkerBackgroundBrush());
RECT arrowRc = {
RECT rcArrow = {
rc.right - NppParameters::getInstance()._dpiManager.scaleX(17), rc.top + 1,
rc.right - 1, rc.bottom - 1
};
bool hasFocus = false;
// CBS_DROPDOWN text is handled by parent by WM_CTLCOLOREDIT
auto style = ::GetWindowLongPtr(hWnd, GWL_STYLE);
if ((style & CBS_DROPDOWNLIST) == CBS_DROPDOWNLIST)
{
RECT bkRc = rc;
bkRc.left += 1;
bkRc.top += 1;
bkRc.right = arrowRc.left - 1;
bkRc.bottom -= 1;
::FillRect(hdc, &bkRc, NppDarkMode::getBackgroundBrush()); // erase background on item change
hasFocus = ::GetFocus() == hWnd;
RECT rcTextBg = rc;
rcTextBg.left += 1;
rcTextBg.top += 1;
rcTextBg.right = rcArrow.left - 1;
rcTextBg.bottom -= 1;
::FillRect(hdc, &rcTextBg, NppDarkMode::getBackgroundBrush()); // erase background on item change
auto index = static_cast<int>(::SendMessage(hWnd, CB_GETCURSEL, 0, 0));
if (index != CB_ERR)
@ -1345,38 +1380,45 @@ namespace NppDarkMode
TCHAR* buffer = new TCHAR[(bufferLen + 1)];
::SendMessage(hWnd, CB_GETLBTEXT, index, reinterpret_cast<LPARAM>(buffer));
RECT textRc = rc;
textRc.left += 4;
textRc.right = arrowRc.left - 5;
RECT rcText = rc;
rcText.left += 4;
rcText.right = rcArrow.left - 5;
::DrawText(hdc, buffer, -1, &textRc, DT_NOPREFIX | DT_LEFT | DT_VCENTER | DT_SINGLELINE);
::DrawText(hdc, buffer, -1, &rcText, DT_NOPREFIX | DT_LEFT | DT_VCENTER | DT_SINGLELINE);
delete[]buffer;
}
}
else if ((style & CBS_DROPDOWN) == CBS_DROPDOWN && hwndEdit != NULL)
{
hasFocus = ::GetFocus() == hwndEdit;
}
POINT ptCursor = {};
::GetCursorPos(&ptCursor);
ScreenToClient(hWnd, &ptCursor);
::ScreenToClient(hWnd, &ptCursor);
bool isHot = PtInRect(&rc, ptCursor);
bool isHot = ::PtInRect(&rc, ptCursor);
::SetTextColor(hdc, isHot ? NppDarkMode::getTextColor() : NppDarkMode::getDarkerTextColor());
::SetBkColor(hdc, isHot ? NppDarkMode::getHotBackgroundColor() : NppDarkMode::getBackgroundColor());
::ExtTextOut(hdc,
arrowRc.left + (arrowRc.right - arrowRc.left) / 2 - NppParameters::getInstance()._dpiManager.scaleX(4),
arrowRc.top + 3,
rcArrow.left + (rcArrow.right - rcArrow.left) / 2 - NppParameters::getInstance()._dpiManager.scaleX(4),
rcArrow.top + 3,
ETO_OPAQUE | ETO_CLIPPED,
&arrowRc, L"˅",
&rcArrow, L"˅",
1,
nullptr);
::SetBkColor(hdc, NppDarkMode::getBackgroundColor());
auto holdPen = static_cast<HPEN>(::SelectObject(hdc, isHot || hasFocus ? NppDarkMode::getHotEdgePen() : NppDarkMode::getEdgePen()));
POINT edge[] = {
{arrowRc.left - 1, arrowRc.top},
{arrowRc.left - 1, arrowRc.bottom}
{rcArrow.left - 1, rcArrow.top},
{rcArrow.left - 1, rcArrow.bottom}
};
::Polyline(hdc, edge, _countof(edge));
::FrameRect(hdc, &rc, isHot || hasFocus ? NppDarkMode::getHotEdgeBrush() : NppDarkMode::getEdgeBrush());
::SelectObject(hdc, holdPen);
::SelectObject(hdc, holdBrush);
@ -1395,7 +1437,14 @@ namespace NppDarkMode
void subclassComboBoxControl(HWND hwnd)
{
SetWindowSubclass(hwnd, ComboBoxSubclass, g_comboBoxSubclassID, 0);
DWORD_PTR hwndEditData = NULL;
auto style = ::GetWindowLongPtr(hwnd, GWL_STYLE);
if ((style & CBS_DROPDOWN) == CBS_DROPDOWN)
{
POINT pt = { 5, 5 };
hwndEditData = reinterpret_cast<DWORD_PTR>(::ChildWindowFromPoint(hwnd, pt));
}
SetWindowSubclass(hwnd, ComboBoxSubclass, g_comboBoxSubclassID, hwndEditData);
}
void autoSubclassAndThemeChildControls(HWND hwndParent, bool subclass, bool theme)

View File

@ -41,6 +41,7 @@ namespace NppDarkMode
COLORREF disabledText = 0;
COLORREF linkText = 0;
COLORREF edge = 0;
COLORREF hotEdge = 0;
};
struct Options
@ -103,6 +104,7 @@ namespace NppDarkMode
COLORREF getLinkTextColor();
COLORREF getEdgeColor();
COLORREF getHotEdgeColor();
HBRUSH getBackgroundBrush();
HBRUSH getDarkerBackgroundBrush();
@ -110,8 +112,12 @@ namespace NppDarkMode
HBRUSH getHotBackgroundBrush();
HBRUSH getErrorBackgroundBrush();
HBRUSH getEdgeBrush();
HBRUSH getHotEdgeBrush();
HPEN getDarkerTextPen();
HPEN getEdgePen();
HPEN getHotEdgePen();
void setBackgroundColor(COLORREF c);
void setSofterBackgroundColor(COLORREF c);