diff --git a/PowerEditor/gcc/makefile b/PowerEditor/gcc/makefile index f060e8600..59fd9414e 100644 --- a/PowerEditor/gcc/makefile +++ b/PowerEditor/gcc/makefile @@ -45,7 +45,7 @@ CPP_DEFINE := UNICODE _UNICODE OEMRESOURCE NOMINMAX _WIN32_WINNT=_WIN32_WINNT_VI LD := $(CXX) LDFLAGS := -municode -mwindows LD_PATH := -LD_LINK := comctl32 crypt32 dbghelp ole32 sensapi shlwapi uuid uxtheme version wininet wintrust +LD_LINK := comctl32 crypt32 dbghelp ole32 sensapi shlwapi uuid uxtheme version wininet wintrust dwmapi LD_LINK += $(patsubst lib%.a,%,$(SCINTILLA_TARGET)) $(patsubst lib%.a,%,$(LEXILLA_TARGET)) imm32 msimg32 ole32 oleaut32 SUBMAKEFLAGS := -O --no-print-directory diff --git a/PowerEditor/src/CMakeLists.txt b/PowerEditor/src/CMakeLists.txt index ee565f52f..111b4d20f 100644 --- a/PowerEditor/src/CMakeLists.txt +++ b/PowerEditor/src/CMakeLists.txt @@ -380,7 +380,7 @@ SET(rcFiles IF (WIN32) SET(option WIN32) - SET(win32_LIBRARIES comctl32 shlwapi dbghelp version crypt32 wintrust sensapi wininet imm32 msimg32 uxtheme) + SET(win32_LIBRARIES comctl32 shlwapi dbghelp version crypt32 wintrust sensapi wininet imm32 msimg32 uxtheme dwmapi) set(CMAKE_CXX_STANDARD 20) if ( MSVC ) #do not use for mingw builds diff --git a/PowerEditor/src/DarkMode/DarkMode.cpp b/PowerEditor/src/DarkMode/DarkMode.cpp index ae39218a8..a3cb830a7 100644 --- a/PowerEditor/src/DarkMode/DarkMode.cpp +++ b/PowerEditor/src/DarkMode/DarkMode.cpp @@ -271,6 +271,11 @@ bool IsWindows11() // or later OS version return (g_buildNumber >= 22000); } +const DWORD GetWindowsBuildNumber() +{ + return g_buildNumber; +} + void InitDarkMode() { fnRtlGetNtVersionNumbers RtlGetNtVersionNumbers = nullptr; diff --git a/PowerEditor/src/DarkMode/DarkMode.h b/PowerEditor/src/DarkMode/DarkMode.h index 507e64480..684b6d65b 100644 --- a/PowerEditor/src/DarkMode/DarkMode.h +++ b/PowerEditor/src/DarkMode/DarkMode.h @@ -17,3 +17,4 @@ void InitDarkMode(); void SetDarkMode(bool useDarkMode, bool fixDarkScrollbar); bool IsWindows10(); bool IsWindows11(); +const DWORD GetWindowsBuildNumber(); diff --git a/PowerEditor/src/MISC/PluginsManager/Notepad_plus_msgs.h b/PowerEditor/src/MISC/PluginsManager/Notepad_plus_msgs.h index 9d3b757dc..1e6b006e3 100644 --- a/PowerEditor/src/MISC/PluginsManager/Notepad_plus_msgs.h +++ b/PowerEditor/src/MISC/PluginsManager/Notepad_plus_msgs.h @@ -549,6 +549,47 @@ enum Platform { PF_UNKNOWN, PF_X86, PF_X64, PF_IA64, PF_ARM64 }; // void* NPPM_GETBOOKMARKID(0, 0) // Returns the bookmark ID + #define NPPM_DARKMODESUBCLASSANDTHEME (NPPMSG + 112) + // ULONG NPPM_DARKMODESUBCLASSANDTHEME(ULONG dmFlags, HWND hwnd) + // Add support for generic dark mode. + // + // Docking panels don't need to call NPPM_DARKMODESUBCLASSANDTHEME for main hwnd. + // Subclassing is applied automatically unless DWS_USEOWNDARKMODE flag is used. + // + // Might not work properly in C# plugins. + // + // Returns succesful combinations of flags. + // + + namespace NppDarkMode + { + // Standard flags for main parent after its children are initialized. + constexpr ULONG dmfInit = 0x0000000BUL; + + // Standard flags for main parent usually used in NPPN_DARKMODECHANGED. + constexpr ULONG dmfHandleChange = 0x0000000CUL; + }; + + // Examples: + // + // - after controls initializations in WM_INITDIALOG, in WM_CREATE or after CreateWindow: + // + //auto success = static_cast(::SendMessage(nppData._nppHandle, NPPM_DARKMODESUBCLASSANDTHEME, static_cast(NppDarkMode::dmfInit), reinterpret_cast(mainHwnd))); + // + // - handling dark mode change: + // + //extern "C" __declspec(dllexport) void beNotified(SCNotification * notifyCode) + //{ + // switch (notifyCode->nmhdr.code) + // { + // case NPPN_DARKMODECHANGED: + // { + // ::SendMessage(nppData._nppHandle, NPPM_DARKMODESUBCLASSANDTHEME, static_cast(dmfHandleChange), reinterpret_cast(mainHwnd)); + // ::SetWindowPos(mainHwnd, nullptr, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); // to redraw titlebar and window + // break; + // } + // } + //} // For RUNCOMMAND_USER diff --git a/PowerEditor/src/NppBigSwitch.cpp b/PowerEditor/src/NppBigSwitch.cpp index 558f90c11..8320b54eb 100644 --- a/PowerEditor/src/NppBigSwitch.cpp +++ b/PowerEditor/src/NppBigSwitch.cpp @@ -3110,6 +3110,11 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa return static_cast(false); } + case NPPM_DARKMODESUBCLASSANDTHEME: + { + return static_cast(NppDarkMode::autoSubclassAndThemePlugin(reinterpret_cast(lParam), static_cast(wParam))); + } + case NPPM_DOCLISTDISABLEPATHCOLUMN: case NPPM_DOCLISTDISABLEEXTCOLUMN: { diff --git a/PowerEditor/src/NppDarkMode.cpp b/PowerEditor/src/NppDarkMode.cpp index 58d00679b..d78c61803 100644 --- a/PowerEditor/src/NppDarkMode.cpp +++ b/PowerEditor/src/NppDarkMode.cpp @@ -20,6 +20,7 @@ #include "DarkMode/DarkMode.h" #include "DarkMode/UAHMenuBar.h" +#include #include #include @@ -33,6 +34,9 @@ #ifdef __GNUC__ #include #define WINAPI_LAMBDA WINAPI +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif #else #define WINAPI_LAMBDA #endif @@ -40,6 +44,7 @@ // already added in project files // keep for plugin authors //#ifdef _MSC_VER +//#pragma comment(lib, "dwmapi.lib") //#pragma comment(lib, "uxtheme.lib") //#endif @@ -548,6 +553,11 @@ namespace NppDarkMode return IsWindows11(); } + const DWORD getWindowsBuildNumber() + { + return GetWindowsBuildNumber(); + } + COLORREF invertLightness(COLORREF c) { WORD h = 0; @@ -2511,16 +2521,15 @@ namespace NppDarkMode case WM_NOTIFY: { - auto nmhdr = reinterpret_cast(lParam); - - constexpr size_t classNameLen = 16; - TCHAR className[classNameLen]{}; - GetClassName(nmhdr->hwndFrom, className, classNameLen); - + const auto nmhdr = reinterpret_cast(lParam); switch (nmhdr->code) { case NM_CUSTOMDRAW: { + constexpr size_t classNameLen = 16; + TCHAR className[classNameLen]{}; + GetClassName(nmhdr->hwndFrom, className, classNameLen); + if (wcscmp(className, TOOLBARCLASSNAME) == 0) { return NppDarkMode::darkToolBarNotifyCustomDraw(lParam); @@ -2550,6 +2559,97 @@ namespace NppDarkMode NppDarkMode::autoSubclassAndThemeChildControls(hwnd, true, g_isAtLeastWindows10); } + ULONG autoSubclassAndThemePlugin(HWND hwnd, ULONG dmFlags) + { + // Used on parent of edit, listbox, static text, treeview, listview and toolbar controls. + // Should be used only one time on parent control after its creation + // even when starting in light mode. + // e.g. in WM_INITDIALOG, in WM_CREATE or after CreateWindow. + constexpr ULONG dmfSubclassParent = 0x00000001UL; + // Should be used only one time on main control/window after initializations of all its children controls + // even when starting in light mode. + // Will also use dmfSetThemeChildren flag. + // e.g. in WM_INITDIALOG, in WM_CREATE or after CreateWindow. + constexpr ULONG dmfSubclassChildren = 0x00000002UL; + // Will apply theme on buttons with style: + // BS_PUSHLIKE, BS_PUSHBUTTON, BS_DEFPUSHBUTTON, BS_SPLITBUTTON or BS_DEFSPLITBUTTON. + // Will apply theme for scrollbars on edit, listbox and rich edit controls. + // Will apply theme for tooltips on listview, treeview and toolbar buttons. + // Should be handled after controls initializations and in NPPN_DARKMODECHANGED. + // Requires at least Windows 10 to work properly. + constexpr ULONG dmfSetThemeChildren = 0x00000004UL; + // Set dark title bar. + // Should be handled after controls initializations and in NPPN_DARKMODECHANGED. + // Requires at least Windows 10 and WS_CAPTION style to work properly. + constexpr ULONG dmfSetTitleBar = 0x00000008UL; + // Will apply dark explorer theme. + // Used mainly for scrollbars and tooltips not handled with dmfSetThemeChildren. + // Might also change style for other elements. + // Should be handled after controls initializations and in NPPN_DARKMODECHANGED. + // Requires at least Windows 10 to work properly. + constexpr ULONG dmfSetThemeDirectly = 0x00000010UL; + + // defined in Notepad_plus_msgs.h + //constexpr ULONG dmfInit = dmfSubclassParent | dmfSubclassChildren | dmfSetTitleBar; // 0x000000BUL + //constexpr ULONG dmfHandleChange = dmfSetThemeChildren | dmfSetTitleBar; // 0x000000CUL + + constexpr ULONG dmfRequiredMask = dmfSubclassParent | dmfSubclassChildren | dmfSetThemeChildren | dmfSetTitleBar | dmfSetThemeDirectly; + //constexpr ULONG dmfAllMask = dmfSubclassParent | dmfSubclassChildren | dmfSetThemeChildren | dmfSetTitleBar | dmfSetThemeDirectly; + + if (hwnd == nullptr || (dmFlags & dmfRequiredMask) == 0) + { + return 0; + } + + auto dmfBitwiseCheck = [dmFlags](ULONG flag) -> bool { + return (dmFlags & flag) == flag; + }; + + ULONG result = 0UL; + + if (dmfBitwiseCheck(dmfSubclassParent)) + { + const bool success = ::SetWindowSubclass(hwnd, PluginDockWindowSubclass, g_pluginDockWindowSubclassID, 0) == TRUE; + if (success) + { + result |= dmfSubclassParent; + } + } + + const bool subclassChildren = dmfBitwiseCheck(dmfSubclassChildren); + if (dmfBitwiseCheck(dmfSetThemeChildren) || subclassChildren) + { + NppDarkMode::autoSubclassAndThemeChildControls(hwnd, subclassChildren, g_isAtLeastWindows10); + result |= dmfSetThemeChildren; + + if (subclassChildren) + { + result |= dmfSubclassChildren; + } + } + + if (dmfBitwiseCheck(dmfSetTitleBar)) + { + const auto style = ::GetWindowLongPtr(hwnd, GWL_STYLE); + if (NppDarkMode::isExperimentalSupported() && ((style & WS_CAPTION) == WS_CAPTION)) + { + NppDarkMode::setDarkTitleBar(hwnd); + result |= dmfSetTitleBar; + } + } + + if (dmfBitwiseCheck(dmfSetThemeDirectly)) + { + if (NppDarkMode::isWindows10()) + { + NppDarkMode::setDarkExplorerTheme(hwnd); + result |= dmfSetThemeDirectly; + } + } + + return result; + } + constexpr UINT_PTR g_windowNotifySubclassID = 42; LRESULT CALLBACK WindowNotifySubclass( @@ -2760,8 +2860,17 @@ namespace NppDarkMode void setDarkTitleBar(HWND hwnd) { - NppDarkMode::allowDarkModeForWindow(hwnd, NppDarkMode::isEnabled()); - NppDarkMode::setTitleBarThemeColor(hwnd); + constexpr DWORD win10Build2004 = 19041; + if (NppDarkMode::getWindowsBuildNumber() >= win10Build2004) + { + BOOL value = NppDarkMode::isEnabled() ? TRUE : FALSE; + ::DwmSetWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value)); + } + else + { + NppDarkMode::allowDarkModeForWindow(hwnd, NppDarkMode::isEnabled()); + NppDarkMode::setTitleBarThemeColor(hwnd); + } } void setDarkExplorerTheme(HWND hwnd) diff --git a/PowerEditor/src/NppDarkMode.h b/PowerEditor/src/NppDarkMode.h index e92a7fdc5..459f5b6b4 100644 --- a/PowerEditor/src/NppDarkMode.h +++ b/PowerEditor/src/NppDarkMode.h @@ -119,6 +119,7 @@ namespace NppDarkMode bool isWindows10(); bool isWindows11(); + const DWORD getWindowsBuildNumber(); COLORREF invertLightness(COLORREF c); COLORREF invertLightnessSofter(COLORREF c); @@ -216,6 +217,7 @@ namespace NppDarkMode LRESULT darkTreeViewNotifyCustomDraw(LPARAM lParam); void autoSubclassAndThemePluginDockWindow(HWND hwnd); + ULONG autoSubclassAndThemePlugin(HWND hwnd, ULONG dmFlags); void autoSubclassAndThemeWindowNotify(HWND hwnd); bool subclassTabUpDownControl(HWND hwnd); diff --git a/PowerEditor/src/ScintillaComponent/GoToLineDlg.cpp b/PowerEditor/src/ScintillaComponent/GoToLineDlg.cpp index 54e1f6f9d..2737ebbba 100644 --- a/PowerEditor/src/ScintillaComponent/GoToLineDlg.cpp +++ b/PowerEditor/src/ScintillaComponent/GoToLineDlg.cpp @@ -20,7 +20,7 @@ intptr_t CALLBACK GoToLineDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM) { - switch (message) + switch (message) { case WM_INITDIALOG : { @@ -135,6 +135,7 @@ intptr_t CALLBACK GoToLineDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM) break; } } + return FALSE; } default : diff --git a/PowerEditor/src/WinControls/FunctionList/functionListPanel.cpp b/PowerEditor/src/WinControls/FunctionList/functionListPanel.cpp index 3cff740ab..d5309a83c 100644 --- a/PowerEditor/src/WinControls/FunctionList/functionListPanel.cpp +++ b/PowerEditor/src/WinControls/FunctionList/functionListPanel.cpp @@ -294,7 +294,7 @@ bool FunctionListPanel::serialize(const generic_string & outputFilename) for (auto & i : j[nodesLabel]) { - if (nodeName == i[nameLabel]) + if (nodeName == std::string{ i[nameLabel] }) { i[leavesLabel].push_back(leafName.c_str()); isFound = true; diff --git a/PowerEditor/visual.net/notepadPlus.Cpp.props b/PowerEditor/visual.net/notepadPlus.Cpp.props index d857bc5d7..581b770d0 100644 --- a/PowerEditor/visual.net/notepadPlus.Cpp.props +++ b/PowerEditor/visual.net/notepadPlus.Cpp.props @@ -42,7 +42,7 @@ NativeRecommendedRules.ruleset - comctl32.lib;shlwapi.lib;shell32.lib;Dbghelp.lib;Version.lib;Crypt32.lib;wintrust.lib;Sensapi.lib;wininet.lib;imm32.lib;msimg32.lib;uxtheme.lib;libscintilla.lib;liblexilla.lib;%(AdditionalDependencies) + comctl32.lib;shlwapi.lib;shell32.lib;Dbghelp.lib;Version.lib;Crypt32.lib;wintrust.lib;Sensapi.lib;wininet.lib;imm32.lib;msimg32.lib;uxtheme.lib;dwmapi.lib;libscintilla.lib;liblexilla.lib;%(AdditionalDependencies) LinkVerboseLib $(OutDir)notepad++.exe 1.0