mirror of
https://github.com/notepad-plus-plus/notepad-plus-plus.git
synced 2025-07-06 13:34:44 +02:00
Add message NPPM_DARKMODESUBCLASSANDTHEME
to allow plugin authors to use generic dark mode. Unfortunately not for C# plugins. related #13572 Fix #13574, close #13596
This commit is contained in:
parent
b88456764b
commit
e7f321f21a
@ -45,7 +45,7 @@ CPP_DEFINE := UNICODE _UNICODE OEMRESOURCE NOMINMAX _WIN32_WINNT=_WIN32_WINNT_VI
|
|||||||
LD := $(CXX)
|
LD := $(CXX)
|
||||||
LDFLAGS := -municode -mwindows
|
LDFLAGS := -municode -mwindows
|
||||||
LD_PATH :=
|
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
|
LD_LINK += $(patsubst lib%.a,%,$(SCINTILLA_TARGET)) $(patsubst lib%.a,%,$(LEXILLA_TARGET)) imm32 msimg32 ole32 oleaut32
|
||||||
SUBMAKEFLAGS := -O --no-print-directory
|
SUBMAKEFLAGS := -O --no-print-directory
|
||||||
|
|
||||||
|
@ -380,7 +380,7 @@ SET(rcFiles
|
|||||||
|
|
||||||
IF (WIN32)
|
IF (WIN32)
|
||||||
SET(option 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)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
if ( MSVC )
|
if ( MSVC )
|
||||||
#do not use for mingw builds
|
#do not use for mingw builds
|
||||||
|
@ -271,6 +271,11 @@ bool IsWindows11() // or later OS version
|
|||||||
return (g_buildNumber >= 22000);
|
return (g_buildNumber >= 22000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DWORD GetWindowsBuildNumber()
|
||||||
|
{
|
||||||
|
return g_buildNumber;
|
||||||
|
}
|
||||||
|
|
||||||
void InitDarkMode()
|
void InitDarkMode()
|
||||||
{
|
{
|
||||||
fnRtlGetNtVersionNumbers RtlGetNtVersionNumbers = nullptr;
|
fnRtlGetNtVersionNumbers RtlGetNtVersionNumbers = nullptr;
|
||||||
|
@ -17,3 +17,4 @@ void InitDarkMode();
|
|||||||
void SetDarkMode(bool useDarkMode, bool fixDarkScrollbar);
|
void SetDarkMode(bool useDarkMode, bool fixDarkScrollbar);
|
||||||
bool IsWindows10();
|
bool IsWindows10();
|
||||||
bool IsWindows11();
|
bool IsWindows11();
|
||||||
|
const DWORD GetWindowsBuildNumber();
|
||||||
|
@ -549,6 +549,47 @@ enum Platform { PF_UNKNOWN, PF_X86, PF_X64, PF_IA64, PF_ARM64 };
|
|||||||
// void* NPPM_GETBOOKMARKID(0, 0)
|
// void* NPPM_GETBOOKMARKID(0, 0)
|
||||||
// Returns the bookmark ID
|
// 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<ULONG>(::SendMessage(nppData._nppHandle, NPPM_DARKMODESUBCLASSANDTHEME, static_cast<WPARAM>(NppDarkMode::dmfInit), reinterpret_cast<LPARAM>(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<WPARAM>(dmfHandleChange), reinterpret_cast<LPARAM>(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
|
// For RUNCOMMAND_USER
|
||||||
|
@ -3110,6 +3110,11 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa
|
|||||||
return static_cast<LRESULT>(false);
|
return static_cast<LRESULT>(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case NPPM_DARKMODESUBCLASSANDTHEME:
|
||||||
|
{
|
||||||
|
return static_cast<LRESULT>(NppDarkMode::autoSubclassAndThemePlugin(reinterpret_cast<HWND>(lParam), static_cast<ULONG>(wParam)));
|
||||||
|
}
|
||||||
|
|
||||||
case NPPM_DOCLISTDISABLEPATHCOLUMN:
|
case NPPM_DOCLISTDISABLEPATHCOLUMN:
|
||||||
case NPPM_DOCLISTDISABLEEXTCOLUMN:
|
case NPPM_DOCLISTDISABLEEXTCOLUMN:
|
||||||
{
|
{
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "DarkMode/DarkMode.h"
|
#include "DarkMode/DarkMode.h"
|
||||||
#include "DarkMode/UAHMenuBar.h"
|
#include "DarkMode/UAHMenuBar.h"
|
||||||
|
|
||||||
|
#include <dwmapi.h>
|
||||||
#include <uxtheme.h>
|
#include <uxtheme.h>
|
||||||
#include <vssym32.h>
|
#include <vssym32.h>
|
||||||
|
|
||||||
@ -33,6 +34,9 @@
|
|||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#define WINAPI_LAMBDA WINAPI
|
#define WINAPI_LAMBDA WINAPI
|
||||||
|
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
|
||||||
|
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#define WINAPI_LAMBDA
|
#define WINAPI_LAMBDA
|
||||||
#endif
|
#endif
|
||||||
@ -40,6 +44,7 @@
|
|||||||
// already added in project files
|
// already added in project files
|
||||||
// keep for plugin authors
|
// keep for plugin authors
|
||||||
//#ifdef _MSC_VER
|
//#ifdef _MSC_VER
|
||||||
|
//#pragma comment(lib, "dwmapi.lib")
|
||||||
//#pragma comment(lib, "uxtheme.lib")
|
//#pragma comment(lib, "uxtheme.lib")
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
@ -548,6 +553,11 @@ namespace NppDarkMode
|
|||||||
return IsWindows11();
|
return IsWindows11();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DWORD getWindowsBuildNumber()
|
||||||
|
{
|
||||||
|
return GetWindowsBuildNumber();
|
||||||
|
}
|
||||||
|
|
||||||
COLORREF invertLightness(COLORREF c)
|
COLORREF invertLightness(COLORREF c)
|
||||||
{
|
{
|
||||||
WORD h = 0;
|
WORD h = 0;
|
||||||
@ -2511,16 +2521,15 @@ namespace NppDarkMode
|
|||||||
|
|
||||||
case WM_NOTIFY:
|
case WM_NOTIFY:
|
||||||
{
|
{
|
||||||
auto nmhdr = reinterpret_cast<LPNMHDR>(lParam);
|
const auto nmhdr = reinterpret_cast<LPNMHDR>(lParam);
|
||||||
|
|
||||||
constexpr size_t classNameLen = 16;
|
|
||||||
TCHAR className[classNameLen]{};
|
|
||||||
GetClassName(nmhdr->hwndFrom, className, classNameLen);
|
|
||||||
|
|
||||||
switch (nmhdr->code)
|
switch (nmhdr->code)
|
||||||
{
|
{
|
||||||
case NM_CUSTOMDRAW:
|
case NM_CUSTOMDRAW:
|
||||||
{
|
{
|
||||||
|
constexpr size_t classNameLen = 16;
|
||||||
|
TCHAR className[classNameLen]{};
|
||||||
|
GetClassName(nmhdr->hwndFrom, className, classNameLen);
|
||||||
|
|
||||||
if (wcscmp(className, TOOLBARCLASSNAME) == 0)
|
if (wcscmp(className, TOOLBARCLASSNAME) == 0)
|
||||||
{
|
{
|
||||||
return NppDarkMode::darkToolBarNotifyCustomDraw(lParam);
|
return NppDarkMode::darkToolBarNotifyCustomDraw(lParam);
|
||||||
@ -2550,6 +2559,97 @@ namespace NppDarkMode
|
|||||||
NppDarkMode::autoSubclassAndThemeChildControls(hwnd, true, g_isAtLeastWindows10);
|
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;
|
constexpr UINT_PTR g_windowNotifySubclassID = 42;
|
||||||
|
|
||||||
LRESULT CALLBACK WindowNotifySubclass(
|
LRESULT CALLBACK WindowNotifySubclass(
|
||||||
@ -2760,8 +2860,17 @@ namespace NppDarkMode
|
|||||||
|
|
||||||
void setDarkTitleBar(HWND hwnd)
|
void setDarkTitleBar(HWND hwnd)
|
||||||
{
|
{
|
||||||
NppDarkMode::allowDarkModeForWindow(hwnd, NppDarkMode::isEnabled());
|
constexpr DWORD win10Build2004 = 19041;
|
||||||
NppDarkMode::setTitleBarThemeColor(hwnd);
|
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)
|
void setDarkExplorerTheme(HWND hwnd)
|
||||||
|
@ -119,6 +119,7 @@ namespace NppDarkMode
|
|||||||
|
|
||||||
bool isWindows10();
|
bool isWindows10();
|
||||||
bool isWindows11();
|
bool isWindows11();
|
||||||
|
const DWORD getWindowsBuildNumber();
|
||||||
|
|
||||||
COLORREF invertLightness(COLORREF c);
|
COLORREF invertLightness(COLORREF c);
|
||||||
COLORREF invertLightnessSofter(COLORREF c);
|
COLORREF invertLightnessSofter(COLORREF c);
|
||||||
@ -216,6 +217,7 @@ namespace NppDarkMode
|
|||||||
LRESULT darkTreeViewNotifyCustomDraw(LPARAM lParam);
|
LRESULT darkTreeViewNotifyCustomDraw(LPARAM lParam);
|
||||||
|
|
||||||
void autoSubclassAndThemePluginDockWindow(HWND hwnd);
|
void autoSubclassAndThemePluginDockWindow(HWND hwnd);
|
||||||
|
ULONG autoSubclassAndThemePlugin(HWND hwnd, ULONG dmFlags);
|
||||||
void autoSubclassAndThemeWindowNotify(HWND hwnd);
|
void autoSubclassAndThemeWindowNotify(HWND hwnd);
|
||||||
|
|
||||||
bool subclassTabUpDownControl(HWND hwnd);
|
bool subclassTabUpDownControl(HWND hwnd);
|
||||||
|
@ -135,6 +135,7 @@ intptr_t CALLBACK GoToLineDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
default :
|
default :
|
||||||
|
@ -294,7 +294,7 @@ bool FunctionListPanel::serialize(const generic_string & outputFilename)
|
|||||||
|
|
||||||
for (auto & i : j[nodesLabel])
|
for (auto & i : j[nodesLabel])
|
||||||
{
|
{
|
||||||
if (nodeName == i[nameLabel])
|
if (nodeName == std::string{ i[nameLabel] })
|
||||||
{
|
{
|
||||||
i[leavesLabel].push_back(leafName.c_str());
|
i[leavesLabel].push_back(leafName.c_str());
|
||||||
isFound = true;
|
isFound = true;
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
<AnalyzeExternalRuleset>NativeRecommendedRules.ruleset</AnalyzeExternalRuleset>
|
<AnalyzeExternalRuleset>NativeRecommendedRules.ruleset</AnalyzeExternalRuleset>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<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;libscintilla.lib;liblexilla.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<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)</AdditionalDependencies>
|
||||||
<ShowProgress>LinkVerboseLib</ShowProgress>
|
<ShowProgress>LinkVerboseLib</ShowProgress>
|
||||||
<OutputFile>$(OutDir)notepad++.exe</OutputFile>
|
<OutputFile>$(OutDir)notepad++.exe</OutputFile>
|
||||||
<Version>1.0</Version>
|
<Version>1.0</Version>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user