mirror of
https://github.com/notepad-plus-plus/notepad-plus-plus.git
synced 2025-07-21 21:04:54 +02:00
Add dark mode in find/replace dialog
Dark Mode find/replace dialog box! Also supporting buffered paint animation for darkmode checkbox/radiobutton control states Close #9800
This commit is contained in:
parent
0dbdef320f
commit
bd6dbd4bb6
@ -7504,6 +7504,7 @@ void Notepad_plus::refreshDarkMode()
|
||||
{
|
||||
SendMessage(_pPublicInterface->getHSelf(), NPPM_SETEDITORBORDEREDGE, 0, NppParameters::getInstance().getSVP()._showBorderEdge);
|
||||
RedrawWindow(_pPublicInterface->getHSelf(), nullptr, nullptr, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN);
|
||||
RedrawWindow(_findReplaceDlg.getHSelf(), nullptr, nullptr, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN);
|
||||
}
|
||||
|
||||
void Notepad_plus::launchDocumentBackupTask()
|
||||
|
@ -226,124 +226,124 @@ namespace NppDarkMode
|
||||
UNREFERENCED_PARAMETER(wParam);
|
||||
switch (message)
|
||||
{
|
||||
case WM_UAHDRAWMENU:
|
||||
case WM_UAHDRAWMENU:
|
||||
{
|
||||
UAHMENU* pUDM = (UAHMENU*)lParam;
|
||||
RECT rc = { 0 };
|
||||
|
||||
// get the menubar rect
|
||||
{
|
||||
UAHMENU* pUDM = (UAHMENU*)lParam;
|
||||
RECT rc = { 0 };
|
||||
MENUBARINFO mbi = { sizeof(mbi) };
|
||||
GetMenuBarInfo(hWnd, OBJID_MENU, 0, &mbi);
|
||||
|
||||
// get the menubar rect
|
||||
{
|
||||
MENUBARINFO mbi = { sizeof(mbi) };
|
||||
GetMenuBarInfo(hWnd, OBJID_MENU, 0, &mbi);
|
||||
RECT rcWindow;
|
||||
GetWindowRect(hWnd, &rcWindow);
|
||||
|
||||
RECT rcWindow;
|
||||
GetWindowRect(hWnd, &rcWindow);
|
||||
// the rcBar is offset by the window rect
|
||||
rc = mbi.rcBar;
|
||||
OffsetRect(&rc, -rcWindow.left, -rcWindow.top);
|
||||
|
||||
// the rcBar is offset by the window rect
|
||||
rc = mbi.rcBar;
|
||||
OffsetRect(&rc, -rcWindow.left, -rcWindow.top);
|
||||
|
||||
rc.top -= 1;
|
||||
}
|
||||
|
||||
FillRect(pUDM->hdc, &rc, NppDarkMode::getPureBackgroundBrush());
|
||||
|
||||
*lr = 0;
|
||||
|
||||
return true;
|
||||
rc.top -= 1;
|
||||
}
|
||||
case WM_UAHDRAWMENUITEM:
|
||||
|
||||
FillRect(pUDM->hdc, &rc, NppDarkMode::getPureBackgroundBrush());
|
||||
|
||||
*lr = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
case WM_UAHDRAWMENUITEM:
|
||||
{
|
||||
UAHDRAWMENUITEM* pUDMI = (UAHDRAWMENUITEM*)lParam;
|
||||
|
||||
// get the menu item string
|
||||
wchar_t menuString[256] = { 0 };
|
||||
MENUITEMINFO mii = { sizeof(mii), MIIM_STRING };
|
||||
{
|
||||
UAHDRAWMENUITEM* pUDMI = (UAHDRAWMENUITEM*)lParam;
|
||||
mii.dwTypeData = menuString;
|
||||
mii.cch = (sizeof(menuString) / 2) - 1;
|
||||
|
||||
// get the menu item string
|
||||
wchar_t menuString[256] = { 0 };
|
||||
MENUITEMINFO mii = { sizeof(mii), MIIM_STRING };
|
||||
{
|
||||
mii.dwTypeData = menuString;
|
||||
mii.cch = (sizeof(menuString) / 2) - 1;
|
||||
|
||||
GetMenuItemInfo(pUDMI->um.hmenu, pUDMI->umi.iPosition, TRUE, &mii);
|
||||
}
|
||||
|
||||
// get the item state for drawing
|
||||
|
||||
DWORD dwFlags = DT_CENTER | DT_SINGLELINE | DT_VCENTER;
|
||||
|
||||
int iTextStateID = MPI_NORMAL;
|
||||
int iBackgroundStateID = MPI_NORMAL;
|
||||
{
|
||||
if ((pUDMI->dis.itemState & ODS_INACTIVE) | (pUDMI->dis.itemState & ODS_DEFAULT))
|
||||
{
|
||||
// normal display
|
||||
iTextStateID = MPI_NORMAL;
|
||||
iBackgroundStateID = MPI_NORMAL;
|
||||
}
|
||||
if (pUDMI->dis.itemState & ODS_HOTLIGHT)
|
||||
{
|
||||
// hot tracking
|
||||
iTextStateID = MPI_HOT;
|
||||
iBackgroundStateID = MPI_HOT;
|
||||
}
|
||||
if (pUDMI->dis.itemState & ODS_SELECTED)
|
||||
{
|
||||
// clicked -- MENU_POPUPITEM has no state for this, though MENU_BARITEM does
|
||||
iTextStateID = MPI_HOT;
|
||||
iBackgroundStateID = MPI_HOT;
|
||||
}
|
||||
if ((pUDMI->dis.itemState & ODS_GRAYED) || (pUDMI->dis.itemState & ODS_DISABLED))
|
||||
{
|
||||
// disabled / grey text
|
||||
iTextStateID = MPI_DISABLED;
|
||||
iBackgroundStateID = MPI_DISABLED;
|
||||
}
|
||||
if (pUDMI->dis.itemState & ODS_NOACCEL)
|
||||
{
|
||||
dwFlags |= DT_HIDEPREFIX;
|
||||
}
|
||||
}
|
||||
|
||||
if (!g_menuTheme)
|
||||
{
|
||||
g_menuTheme = OpenThemeData(hWnd, L"Menu");
|
||||
}
|
||||
|
||||
if (iBackgroundStateID == MPI_NORMAL || iBackgroundStateID == MPI_DISABLED)
|
||||
{
|
||||
FillRect(pUDMI->um.hdc, &pUDMI->dis.rcItem, NppDarkMode::getPureBackgroundBrush());
|
||||
}
|
||||
else if (iBackgroundStateID == MPI_HOT || iBackgroundStateID == MPI_DISABLEDHOT)
|
||||
{
|
||||
FillRect(pUDMI->um.hdc, &pUDMI->dis.rcItem, NppDarkMode::getHotBackgroundBrush());
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawThemeBackground(g_menuTheme, pUDMI->um.hdc, MENU_POPUPITEM, iBackgroundStateID, &pUDMI->dis.rcItem, nullptr);
|
||||
}
|
||||
DTTOPTS dttopts = { sizeof(dttopts) };
|
||||
if (iTextStateID == MPI_NORMAL || iTextStateID == MPI_HOT)
|
||||
{
|
||||
dttopts.dwFlags |= DTT_TEXTCOLOR;
|
||||
dttopts.crText = NppDarkMode::getTextColor();
|
||||
}
|
||||
DrawThemeTextEx(g_menuTheme, pUDMI->um.hdc, MENU_POPUPITEM, iTextStateID, menuString, mii.cch, dwFlags, &pUDMI->dis.rcItem, &dttopts);
|
||||
|
||||
*lr = 0;
|
||||
|
||||
return true;
|
||||
GetMenuItemInfo(pUDMI->um.hmenu, pUDMI->umi.iPosition, TRUE, &mii);
|
||||
}
|
||||
case WM_THEMECHANGED:
|
||||
|
||||
// get the item state for drawing
|
||||
|
||||
DWORD dwFlags = DT_CENTER | DT_SINGLELINE | DT_VCENTER;
|
||||
|
||||
int iTextStateID = MPI_NORMAL;
|
||||
int iBackgroundStateID = MPI_NORMAL;
|
||||
{
|
||||
if (g_menuTheme)
|
||||
if ((pUDMI->dis.itemState & ODS_INACTIVE) | (pUDMI->dis.itemState & ODS_DEFAULT))
|
||||
{
|
||||
CloseThemeData(g_menuTheme);
|
||||
g_menuTheme = nullptr;
|
||||
// normal display
|
||||
iTextStateID = MPI_NORMAL;
|
||||
iBackgroundStateID = MPI_NORMAL;
|
||||
}
|
||||
if (pUDMI->dis.itemState & ODS_HOTLIGHT)
|
||||
{
|
||||
// hot tracking
|
||||
iTextStateID = MPI_HOT;
|
||||
iBackgroundStateID = MPI_HOT;
|
||||
}
|
||||
if (pUDMI->dis.itemState & ODS_SELECTED)
|
||||
{
|
||||
// clicked -- MENU_POPUPITEM has no state for this, though MENU_BARITEM does
|
||||
iTextStateID = MPI_HOT;
|
||||
iBackgroundStateID = MPI_HOT;
|
||||
}
|
||||
if ((pUDMI->dis.itemState & ODS_GRAYED) || (pUDMI->dis.itemState & ODS_DISABLED))
|
||||
{
|
||||
// disabled / grey text
|
||||
iTextStateID = MPI_DISABLED;
|
||||
iBackgroundStateID = MPI_DISABLED;
|
||||
}
|
||||
if (pUDMI->dis.itemState & ODS_NOACCEL)
|
||||
{
|
||||
dwFlags |= DT_HIDEPREFIX;
|
||||
}
|
||||
// continue processing in main wndproc
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
|
||||
if (!g_menuTheme)
|
||||
{
|
||||
g_menuTheme = OpenThemeData(hWnd, L"Menu");
|
||||
}
|
||||
|
||||
if (iBackgroundStateID == MPI_NORMAL || iBackgroundStateID == MPI_DISABLED)
|
||||
{
|
||||
FillRect(pUDMI->um.hdc, &pUDMI->dis.rcItem, NppDarkMode::getPureBackgroundBrush());
|
||||
}
|
||||
else if (iBackgroundStateID == MPI_HOT || iBackgroundStateID == MPI_DISABLEDHOT)
|
||||
{
|
||||
FillRect(pUDMI->um.hdc, &pUDMI->dis.rcItem, NppDarkMode::getHotBackgroundBrush());
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawThemeBackground(g_menuTheme, pUDMI->um.hdc, MENU_POPUPITEM, iBackgroundStateID, &pUDMI->dis.rcItem, nullptr);
|
||||
}
|
||||
DTTOPTS dttopts = { sizeof(dttopts) };
|
||||
if (iTextStateID == MPI_NORMAL || iTextStateID == MPI_HOT)
|
||||
{
|
||||
dttopts.dwFlags |= DTT_TEXTCOLOR;
|
||||
dttopts.crText = NppDarkMode::getTextColor();
|
||||
}
|
||||
DrawThemeTextEx(g_menuTheme, pUDMI->um.hdc, MENU_POPUPITEM, iTextStateID, menuString, mii.cch, dwFlags, &pUDMI->dis.rcItem, &dttopts);
|
||||
|
||||
*lr = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
case WM_THEMECHANGED:
|
||||
{
|
||||
if (g_menuTheme)
|
||||
{
|
||||
CloseThemeData(g_menuTheme);
|
||||
g_menuTheme = nullptr;
|
||||
}
|
||||
// continue processing in main wndproc
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -377,6 +377,7 @@ namespace NppDarkMode
|
||||
struct ButtonData
|
||||
{
|
||||
HTHEME hTheme = nullptr;
|
||||
int iStateID = 0;
|
||||
|
||||
~ButtonData()
|
||||
{
|
||||
@ -402,44 +403,19 @@ namespace NppDarkMode
|
||||
}
|
||||
};
|
||||
|
||||
void paintButton(HWND hwnd, HDC hdc, ButtonData& buttonData)
|
||||
void renderButton(HWND hwnd, HDC hdc, HTHEME hTheme, int iPartID, int iStateID)
|
||||
{
|
||||
RECT rcClient = { 0 };
|
||||
WCHAR szText[256] = { 0 };
|
||||
DWORD nState = static_cast<DWORD>(SendMessage(hwnd, BM_GETSTATE, 0, 0));
|
||||
bool isEnabled = IsWindowEnabled(hwnd);;
|
||||
DWORD uiState = static_cast<DWORD>(SendMessage(hwnd, WM_QUERYUISTATE, 0, 0));
|
||||
DWORD nStyle = GetWindowLong(hwnd, GWL_STYLE);
|
||||
DWORD nButtonStyle = nStyle & 0xF;
|
||||
|
||||
int iPartID = BP_CHECKBOX;
|
||||
if (nButtonStyle == BS_CHECKBOX || nButtonStyle == BS_AUTOCHECKBOX)
|
||||
{
|
||||
iPartID = BP_CHECKBOX;
|
||||
}
|
||||
else if (nButtonStyle == BS_RADIOBUTTON || nButtonStyle == BS_AUTORADIOBUTTON)
|
||||
{
|
||||
iPartID = BP_RADIOBUTTON;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
// states of BP_CHECKBOX and BP_RADIOBUTTON are the same
|
||||
int iStateID = RBS_UNCHECKEDNORMAL;
|
||||
|
||||
if (!isEnabled) iStateID = RBS_UNCHECKEDDISABLED;
|
||||
else if (nState & BST_PUSHED) iStateID = RBS_UNCHECKEDPRESSED;
|
||||
else if (nState & BST_HOT) iStateID = RBS_UNCHECKEDHOT;
|
||||
|
||||
if (nState & BST_CHECKED) iStateID += 4;
|
||||
|
||||
HFONT hFont = nullptr;
|
||||
HFONT hOldFont = nullptr;
|
||||
HFONT hCreatedFont = nullptr;
|
||||
LOGFONT lf = { 0 };
|
||||
if (SUCCEEDED(GetThemeFont(buttonData.hTheme, hdc, iPartID, iStateID, TMT_FONT, &lf)))
|
||||
if (SUCCEEDED(GetThemeFont(hTheme, hdc, iPartID, iStateID, TMT_FONT, &lf)))
|
||||
{
|
||||
hCreatedFont = CreateFontIndirect(&lf);
|
||||
hFont = hCreatedFont;
|
||||
@ -466,10 +442,10 @@ namespace NppDarkMode
|
||||
GetWindowText(hwnd, szText, _countof(szText));
|
||||
|
||||
SIZE szBox = { 13, 13 };
|
||||
GetThemePartSize(buttonData.hTheme, hdc, iPartID, iStateID, NULL, TS_DRAW, &szBox);
|
||||
GetThemePartSize(hTheme, hdc, iPartID, iStateID, NULL, TS_DRAW, &szBox);
|
||||
|
||||
RECT rcText = rcClient;
|
||||
GetThemeBackgroundContentRect(buttonData.hTheme, hdc, iPartID, iStateID, &rcClient, &rcText);
|
||||
GetThemeBackgroundContentRect(hTheme, hdc, iPartID, iStateID, &rcClient, &rcText);
|
||||
|
||||
RECT rcBackground = rcClient;
|
||||
if (dtFlags & DT_SINGLELINE)
|
||||
@ -481,18 +457,18 @@ namespace NppDarkMode
|
||||
rcText.left = rcBackground.right + 3;
|
||||
|
||||
DrawThemeParentBackground(hwnd, hdc, &rcClient);
|
||||
DrawThemeBackground(buttonData.hTheme, hdc, iPartID, iStateID, &rcBackground, nullptr);
|
||||
DrawThemeBackground(hTheme, hdc, iPartID, iStateID, &rcBackground, nullptr);
|
||||
|
||||
DTTOPTS dtto = { sizeof(DTTOPTS), DTT_TEXTCOLOR };
|
||||
dtto.crText = NppDarkMode::getTextColor();
|
||||
|
||||
DrawThemeTextEx(buttonData.hTheme, hdc, iPartID, iStateID, szText, -1, dtFlags, &rcText, &dtto);
|
||||
DrawThemeTextEx(hTheme, hdc, iPartID, iStateID, szText, -1, dtFlags, &rcText, &dtto);
|
||||
|
||||
if ((nState & BST_FOCUS) && !(uiState & UISF_HIDEFOCUS))
|
||||
{
|
||||
RECT rcTextOut = rcText;
|
||||
dtto.dwFlags |= DTT_CALCRECT;
|
||||
DrawThemeTextEx(buttonData.hTheme, hdc, iPartID, iStateID, szText, -1, dtFlags | DT_CALCRECT, &rcTextOut, &dtto);
|
||||
DrawThemeTextEx(hTheme, hdc, iPartID, iStateID, szText, -1, dtFlags | DT_CALCRECT, &rcTextOut, &dtto);
|
||||
RECT rcFocus = rcTextOut;
|
||||
rcFocus.bottom++;
|
||||
rcFocus.left--;
|
||||
@ -504,6 +480,76 @@ namespace NppDarkMode
|
||||
SelectObject(hdc, hOldFont);
|
||||
}
|
||||
|
||||
void paintButton(HWND hwnd, HDC hdc, ButtonData& buttonData)
|
||||
{
|
||||
DWORD nState = static_cast<DWORD>(SendMessage(hwnd, BM_GETSTATE, 0, 0));
|
||||
DWORD nStyle = GetWindowLong(hwnd, GWL_STYLE);
|
||||
DWORD nButtonStyle = nStyle & 0xF;
|
||||
|
||||
int iPartID = BP_CHECKBOX;
|
||||
if (nButtonStyle == BS_CHECKBOX || nButtonStyle == BS_AUTOCHECKBOX)
|
||||
{
|
||||
iPartID = BP_CHECKBOX;
|
||||
}
|
||||
else if (nButtonStyle == BS_RADIOBUTTON || nButtonStyle == BS_AUTORADIOBUTTON)
|
||||
{
|
||||
iPartID = BP_RADIOBUTTON;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
// states of BP_CHECKBOX and BP_RADIOBUTTON are the same
|
||||
int iStateID = RBS_UNCHECKEDNORMAL;
|
||||
|
||||
if (nStyle & WS_DISABLED) iStateID = RBS_UNCHECKEDDISABLED;
|
||||
else if (nState & BST_PUSHED) iStateID = RBS_UNCHECKEDPRESSED;
|
||||
else if (nState & BST_HOT) iStateID = RBS_UNCHECKEDHOT;
|
||||
|
||||
if (nState & BST_CHECKED) iStateID += 4;
|
||||
|
||||
if (BufferedPaintRenderAnimation(hwnd, hdc))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BP_ANIMATIONPARAMS animParams = { sizeof(animParams) };
|
||||
animParams.style = BPAS_LINEAR;
|
||||
if (iStateID != buttonData.iStateID)
|
||||
{
|
||||
GetThemeTransitionDuration(buttonData.hTheme, iPartID, buttonData.iStateID, iStateID, TMT_TRANSITIONDURATIONS, &animParams.dwDuration);
|
||||
}
|
||||
|
||||
RECT rcClient = { 0 };
|
||||
GetClientRect(hwnd, &rcClient);
|
||||
|
||||
HDC hdcFrom = nullptr;
|
||||
HDC hdcTo = nullptr;
|
||||
HANIMATIONBUFFER hbpAnimation = BeginBufferedAnimation(hwnd, hdc, &rcClient, BPBF_COMPATIBLEBITMAP, nullptr, &animParams, &hdcFrom, &hdcTo);
|
||||
if (hbpAnimation)
|
||||
{
|
||||
if (hdcFrom)
|
||||
{
|
||||
renderButton(hwnd, hdcFrom, buttonData.hTheme, iPartID, buttonData.iStateID);
|
||||
}
|
||||
if (hdcTo)
|
||||
{
|
||||
renderButton(hwnd, hdcTo, buttonData.hTheme, iPartID, iStateID);
|
||||
}
|
||||
|
||||
buttonData.iStateID = iStateID;
|
||||
|
||||
EndBufferedAnimation(hbpAnimation, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderButton(hwnd, hdc, buttonData.hTheme, iPartID, iStateID);
|
||||
|
||||
buttonData.iStateID = iStateID;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr UINT_PTR g_buttonSubclassID = 42;
|
||||
|
||||
LRESULT CALLBACK ButtonSubclass(
|
||||
@ -567,6 +613,10 @@ namespace NppDarkMode
|
||||
{
|
||||
break;
|
||||
}
|
||||
case WM_SIZE:
|
||||
case WM_DESTROY:
|
||||
BufferedPaintStopAllAnimations(hWnd);
|
||||
break;
|
||||
}
|
||||
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
@ -577,6 +627,153 @@ namespace NppDarkMode
|
||||
SetWindowSubclass(hwnd, ButtonSubclass, g_buttonSubclassID, pButtonData);
|
||||
}
|
||||
|
||||
void paintGroupbox(HWND hwnd, HDC hdc, ButtonData& buttonData)
|
||||
{
|
||||
DWORD nStyle = GetWindowLong(hwnd, GWL_STYLE);
|
||||
int iPartID = BP_GROUPBOX;
|
||||
int iStateID = GBS_NORMAL;
|
||||
|
||||
if (nStyle & WS_DISABLED)
|
||||
{
|
||||
iStateID = GBS_DISABLED;
|
||||
}
|
||||
|
||||
RECT rcClient = { 0 };
|
||||
GetClientRect(hwnd, &rcClient);
|
||||
|
||||
RECT rcText = rcClient;
|
||||
RECT rcBackground = rcClient;
|
||||
|
||||
HFONT hFont = nullptr;
|
||||
HFONT hOldFont = nullptr;
|
||||
HFONT hCreatedFont = nullptr;
|
||||
LOGFONT lf = { 0 };
|
||||
if (SUCCEEDED(GetThemeFont(buttonData.hTheme, hdc, iPartID, iStateID, TMT_FONT, &lf)))
|
||||
{
|
||||
hCreatedFont = CreateFontIndirect(&lf);
|
||||
hFont = hCreatedFont;
|
||||
}
|
||||
|
||||
if (!hFont) {
|
||||
hFont = reinterpret_cast<HFONT>(SendMessage(hwnd, WM_GETFONT, 0, 0));
|
||||
}
|
||||
|
||||
SelectObject(hdc, hFont);
|
||||
|
||||
|
||||
WCHAR szText[256] = { 0 };
|
||||
GetWindowText(hwnd, szText, _countof(szText));
|
||||
|
||||
if (szText[0])
|
||||
{
|
||||
SIZE textSize = { 0 };
|
||||
GetTextExtentPoint32(hdc, szText, static_cast<int>(wcslen(szText)), &textSize);
|
||||
rcBackground.top += textSize.cy / 2;
|
||||
rcText.left += 7;
|
||||
rcText.bottom = rcText.top + textSize.cy;
|
||||
rcText.right = rcText.left + textSize.cx + 4;
|
||||
|
||||
ExcludeClipRect(hdc, rcText.left, rcText.top, rcText.right, rcText.bottom);
|
||||
}
|
||||
else
|
||||
{
|
||||
SIZE textSize = { 0 };
|
||||
GetTextExtentPoint32(hdc, L"M", 1, &textSize);
|
||||
rcBackground.top += textSize.cy / 2;
|
||||
}
|
||||
|
||||
RECT rcContent = rcBackground;
|
||||
GetThemeBackgroundContentRect(buttonData.hTheme, hdc, BP_GROUPBOX, iStateID, &rcBackground, &rcContent);
|
||||
ExcludeClipRect(hdc, rcContent.left, rcContent.top, rcContent.right, rcContent.bottom);
|
||||
|
||||
DrawThemeParentBackground(hwnd, hdc, &rcClient);
|
||||
DrawThemeBackground(buttonData.hTheme, hdc, BP_GROUPBOX, iStateID, &rcBackground, nullptr);
|
||||
|
||||
SelectClipRgn(hdc, nullptr);
|
||||
|
||||
if (szText[0])
|
||||
{
|
||||
rcText.right -= 2;
|
||||
rcText.left += 2;
|
||||
|
||||
DTTOPTS dtto = { sizeof(DTTOPTS), DTT_TEXTCOLOR };
|
||||
dtto.crText = NppDarkMode::getTextColor();
|
||||
|
||||
DrawThemeTextEx(buttonData.hTheme, hdc, BP_GROUPBOX, iStateID, szText, -1, DT_LEFT | DT_SINGLELINE, &rcText, &dtto);
|
||||
}
|
||||
|
||||
if (hCreatedFont) DeleteObject(hCreatedFont);
|
||||
SelectObject(hdc, hOldFont);
|
||||
}
|
||||
|
||||
constexpr UINT_PTR g_groupboxSubclassID = 42;
|
||||
|
||||
LRESULT CALLBACK GroupboxSubclass(
|
||||
HWND hWnd,
|
||||
UINT uMsg,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam,
|
||||
UINT_PTR uIdSubclass,
|
||||
DWORD_PTR dwRefData
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(uIdSubclass);
|
||||
|
||||
auto pButtonData = reinterpret_cast<ButtonData*>(dwRefData);
|
||||
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_NCDESTROY:
|
||||
RemoveWindowSubclass(hWnd, GroupboxSubclass, g_groupboxSubclassID);
|
||||
delete pButtonData;
|
||||
break;
|
||||
case WM_ERASEBKGND:
|
||||
if (NppDarkMode::isEnabled() && pButtonData->ensureTheme(hWnd))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
case WM_THEMECHANGED:
|
||||
pButtonData->closeTheme();
|
||||
break;
|
||||
case WM_PRINTCLIENT:
|
||||
case WM_PAINT:
|
||||
if (NppDarkMode::isEnabled() && pButtonData->ensureTheme(hWnd))
|
||||
{
|
||||
PAINTSTRUCT ps = { 0 };
|
||||
HDC hdc = reinterpret_cast<HDC>(wParam);
|
||||
if (!hdc)
|
||||
{
|
||||
hdc = BeginPaint(hWnd, &ps);
|
||||
}
|
||||
|
||||
paintGroupbox(hWnd, hdc, *pButtonData);
|
||||
|
||||
if (ps.hdc)
|
||||
{
|
||||
EndPaint(hWnd, &ps);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
void subclassGroupboxControl(HWND hwnd)
|
||||
{
|
||||
DWORD_PTR pButtonData = reinterpret_cast<DWORD_PTR>(new ButtonData());
|
||||
SetWindowSubclass(hwnd, GroupboxSubclass, g_groupboxSubclassID, pButtonData);
|
||||
}
|
||||
|
||||
constexpr UINT_PTR g_toolbarSubclassID = 42;
|
||||
|
||||
LRESULT CALLBACK ToolbarSubclass(
|
||||
@ -604,5 +801,136 @@ namespace NppDarkMode
|
||||
{
|
||||
SetWindowSubclass(hwnd, ToolbarSubclass, g_toolbarSubclassID, 0);
|
||||
}
|
||||
|
||||
constexpr UINT_PTR g_tabSubclassID = 42;
|
||||
|
||||
LRESULT CALLBACK TabSubclass(
|
||||
HWND hWnd,
|
||||
UINT uMsg,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam,
|
||||
UINT_PTR uIdSubclass,
|
||||
DWORD_PTR dwRefData
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(uIdSubclass);
|
||||
UNREFERENCED_PARAMETER(dwRefData);
|
||||
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_PAINT:
|
||||
{
|
||||
if (!NppDarkMode::isEnabled())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
LONG_PTR dwStyle = GetWindowLongPtr(hWnd, GWL_STYLE);
|
||||
if ((dwStyle & TCS_BOTTOM) || (dwStyle & TCS_BUTTONS) || (dwStyle & TCS_VERTICAL))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc = BeginPaint(hWnd, &ps);
|
||||
FillRect(hdc, &ps.rcPaint, NppDarkMode::getPureBackgroundBrush());
|
||||
|
||||
static HPEN g_hpen = CreatePen(PS_SOLID, 1, NppDarkMode::getEdgeColor());
|
||||
|
||||
HPEN holdPen = (HPEN)SelectObject(hdc, g_hpen);
|
||||
|
||||
HRGN holdClip = CreateRectRgn(0, 0, 0, 0);
|
||||
if (1 != GetClipRgn(hdc, holdClip))
|
||||
{
|
||||
DeleteObject(holdClip);
|
||||
holdClip = nullptr;
|
||||
}
|
||||
|
||||
HFONT hFont = reinterpret_cast<HFONT>(SendMessage(hWnd, WM_GETFONT, 0, 0));
|
||||
auto hOldFont = SelectObject(hdc, hFont);
|
||||
|
||||
POINT ptCursor = { 0 };
|
||||
::GetCursorPos(&ptCursor);
|
||||
ScreenToClient(hWnd, &ptCursor);
|
||||
|
||||
int nTabs = TabCtrl_GetItemCount(hWnd);
|
||||
|
||||
int nSelTab = TabCtrl_GetCurSel(hWnd);
|
||||
for (int i = 0; i < nTabs; ++i)
|
||||
{
|
||||
RECT rcItem = { 0 };
|
||||
TabCtrl_GetItemRect(hWnd, i, &rcItem);
|
||||
|
||||
RECT rcIntersect = { 0 };
|
||||
if (IntersectRect(&rcIntersect, &ps.rcPaint, &rcItem))
|
||||
{
|
||||
bool bHot = PtInRect(&rcItem, ptCursor);
|
||||
|
||||
POINT edges[] = {
|
||||
{rcItem.right - 1, rcItem.top},
|
||||
{rcItem.right - 1, rcItem.bottom}
|
||||
};
|
||||
Polyline(hdc, edges, _countof(edges));
|
||||
rcItem.right -= 1;
|
||||
|
||||
HRGN hClip = CreateRectRgnIndirect(&rcItem);
|
||||
|
||||
SelectClipRgn(hdc, hClip);
|
||||
|
||||
SetTextColor(hdc, (bHot || (i == nSelTab) ) ? NppDarkMode::getTextColor() : NppDarkMode::getDarkerTextColor());
|
||||
|
||||
FillRect(hdc, &rcItem, (i == nSelTab) ? NppDarkMode::getPureBackgroundBrush() : NppDarkMode::getBackgroundBrush());
|
||||
|
||||
SetBkMode(hdc, TRANSPARENT);
|
||||
|
||||
TCHAR label[MAX_PATH];
|
||||
TCITEM tci = { 0 };
|
||||
tci.mask = TCIF_TEXT;
|
||||
tci.pszText = label;
|
||||
tci.cchTextMax = MAX_PATH - 1;
|
||||
|
||||
::SendMessage(hWnd, TCM_GETITEM, i, reinterpret_cast<LPARAM>(&tci));
|
||||
|
||||
RECT rcText = rcItem;
|
||||
rcText.left += NppParameters::getInstance()._dpiManager.scaleX(6);
|
||||
rcText.right -= NppParameters::getInstance()._dpiManager.scaleX(3);
|
||||
|
||||
if (i == nSelTab) {
|
||||
rcText.bottom -= NppParameters::getInstance()._dpiManager.scaleX(4);
|
||||
}
|
||||
|
||||
DrawText(hdc, label, -1, &rcText, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
|
||||
|
||||
DeleteObject(hClip);
|
||||
|
||||
SelectClipRgn(hdc, holdClip);
|
||||
}
|
||||
}
|
||||
|
||||
SelectObject(hdc, hOldFont);
|
||||
|
||||
SelectClipRgn(hdc, holdClip);
|
||||
if (holdClip)
|
||||
{
|
||||
DeleteObject(holdClip);
|
||||
holdClip = nullptr;
|
||||
}
|
||||
|
||||
SelectObject(hdc, holdPen);
|
||||
|
||||
EndPaint(hWnd, &ps);
|
||||
return 0;
|
||||
}
|
||||
case WM_NCDESTROY:
|
||||
RemoveWindowSubclass(hWnd, TabSubclass, g_tabSubclassID);
|
||||
break;
|
||||
}
|
||||
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
void subclassTabControl(HWND hwnd)
|
||||
{
|
||||
SetWindowSubclass(hwnd, TabSubclass, g_tabSubclassID, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,8 @@ namespace NppDarkMode
|
||||
void enableDarkScrollBarForWindowAndChildren(HWND hwnd);
|
||||
|
||||
void subclassButtonControl(HWND hwnd);
|
||||
void subclassGroupboxControl(HWND hwnd);
|
||||
void subclassToolbarControl(HWND hwnd);
|
||||
void subclassTabControl(HWND hwnd);
|
||||
}
|
||||
|
||||
|
@ -272,6 +272,7 @@ void FindReplaceDlg::create(int dialogID, bool isRTL, bool msgDestParent)
|
||||
//::GetWindowRect(_hSelf, &rect);
|
||||
getClientRect(rect);
|
||||
_tab.init(_hInst, _hSelf, false, true);
|
||||
NppDarkMode::subclassTabControl(_tab.getHSelf());
|
||||
int tabDpiDynamicalHeight = NppParameters::getInstance()._dpiManager.scaleY(13);
|
||||
_tab.setFont(TEXT("Tahoma"), tabDpiDynamicalHeight);
|
||||
|
||||
@ -848,8 +849,72 @@ INT_PTR CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
case WM_CTLCOLOREDIT:
|
||||
case WM_CTLCOLORDLG:
|
||||
case WM_CTLCOLORSTATIC:
|
||||
{
|
||||
if (!NppDarkMode::isEnabled())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
SetTextColor((HDC)wParam, NppDarkMode::getTextColor());
|
||||
SetBkColor((HDC)wParam, NppDarkMode::getPureBackgroundColor());
|
||||
return (LRESULT)GetStockObject(BLACK_BRUSH);
|
||||
}
|
||||
case WM_PRINTCLIENT:
|
||||
case WM_ERASEBKGND:
|
||||
{
|
||||
if (!NppDarkMode::isEnabled())
|
||||
{
|
||||
break;
|
||||
}
|
||||
RECT rc = { 0 };
|
||||
getClientRect(rc);
|
||||
FillRect((HDC)wParam, &rc, NppDarkMode::getPureBackgroundBrush());
|
||||
SetWindowLongPtr(_hSelf, DWLP_MSGRESULT, TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
case WM_SETTINGCHANGE:
|
||||
{
|
||||
if (NppDarkMode::handleSettingChange(_hSelf, lParam))
|
||||
{
|
||||
// dark mode may have been toggled by the OS
|
||||
NppDarkMode::refreshDarkMode(_hSelf, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_INITDIALOG :
|
||||
{
|
||||
if (NppDarkMode::isExperimentalEnabled())
|
||||
{
|
||||
NppDarkMode::allowDarkModeForWindow(_hSelf, true);
|
||||
NppDarkMode::refreshTitleBarThemeColor(_hSelf);
|
||||
}
|
||||
|
||||
EnumChildWindows(_hSelf, [](HWND hwnd, LPARAM) {
|
||||
wchar_t className[16] = { 0 };
|
||||
GetClassName(hwnd, className, 9);
|
||||
if (wcscmp(className, L"Button")) {
|
||||
return TRUE;
|
||||
}
|
||||
DWORD nButtonStyle = (DWORD)GetWindowLong(hwnd, GWL_STYLE) & 0xF;
|
||||
switch (nButtonStyle) {
|
||||
case BS_CHECKBOX:
|
||||
case BS_AUTOCHECKBOX:
|
||||
case BS_RADIOBUTTON:
|
||||
case BS_AUTORADIOBUTTON:
|
||||
NppDarkMode::subclassButtonControl(hwnd);
|
||||
break;
|
||||
case BS_GROUPBOX:
|
||||
NppDarkMode::subclassGroupboxControl(hwnd);
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}, NULL);
|
||||
|
||||
HWND hFindCombo = ::GetDlgItem(_hSelf, IDFINDWHAT);
|
||||
HWND hReplaceCombo = ::GetDlgItem(_hSelf, IDREPLACEWITH);
|
||||
HWND hFiltersCombo = ::GetDlgItem(_hSelf, IDD_FINDINFILES_FILTERS_COMBO);
|
||||
@ -957,6 +1022,7 @@ INT_PTR CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM
|
||||
|
||||
::SetWindowTextW(::GetDlgItem(_hSelf, IDC_FINDPREV), TEXT("▲"));
|
||||
::SetWindowTextW(::GetDlgItem(_hSelf, IDC_FINDNEXT), TEXT("▼ Find Next"));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ BEGIN
|
||||
CONTROL "Backward direction", IDC_BACKWARDDIRECTION, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 12, 76, 140, 15
|
||||
CONTROL "Match &whole word only",IDWHOLEWORD,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,88,140,15
|
||||
CONTROL "Match &case",IDMATCHCASE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,100,140,15
|
||||
CONTROL "Wra&p around",IDWRAP,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,12,112,140,15
|
||||
CONTROL "Wra&p around",IDWRAP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,112,140,15
|
||||
GROUPBOX "Search Mode",IDC_MODE_STATIC,6,131,159,48
|
||||
CONTROL "&Normal",IDNORMAL,"Button",BS_AUTORADIOBUTTON | WS_GROUP,12,143,126,10
|
||||
CONTROL "E&xtended (\\n, \\r, \\t, \\0, \\x...)",IDEXTENDED,
|
||||
|
Loading…
x
Reference in New Issue
Block a user