From 9cf97b65760a3fe6edffa4e2b00836b1b1307604 Mon Sep 17 00:00:00 2001 From: gongao21 <1793839835@qq.com> Date: Mon, 22 Jan 2024 21:34:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=AB=E5=82=B2=20=E6=97=A0=E6=95=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/PowerEditor/src/NppDarkMode.cpp | 73 ++++++++++++++++++++++------- src/PowerEditor/src/NppDarkMode.h | 44 ++++++++--------- 2 files changed, 78 insertions(+), 39 deletions(-) diff --git a/src/PowerEditor/src/NppDarkMode.cpp b/src/PowerEditor/src/NppDarkMode.cpp index 27b57c7..b1dfb63 100644 --- a/src/PowerEditor/src/NppDarkMode.cpp +++ b/src/PowerEditor/src/NppDarkMode.cpp @@ -1560,13 +1560,17 @@ namespace NppDarkMode return DefSubclassProc(hWnd, uMsg, wParam, lParam); } + //窗口子类化的示例,它为指定的窗口处理了自定义的边框绘制逻辑。 void subclassTabControl(HWND hwnd) { - SetWindowSubclass(hwnd, TabSubclass, g_tabSubclassID, 0); + SetWindowSubclass(hwnd, TabSubclass, g_tabSubclassID, 0); //将窗口 hwnd 子类化为 TabSubclass,并分配一个唯一的子类 ID g_tabSubclassID。 } constexpr UINT_PTR g_customBorderSubclassID = 42; + //这个函数是一个回调函数,用于处理窗口消息。它被用作窗口子类的回调函数。 + //当窗口接收到消息时,该函数会被调用来处理消息。 + //注意,该函数的签名必须与 SUBCLASSPROC 类型匹配。 LRESULT CALLBACK CustomBorderSubclass( HWND hWnd, UINT uMsg, @@ -1580,6 +1584,9 @@ namespace NppDarkMode static bool isHotStatic = false; + //在这个函数中,根据不同的消息类型进行不同的处理。 + //其中,WM_NCPAINT 消息用于非客户区绘制,即窗口的边框绘制。 + //在这里,通过重绘窗口的边框,实现了自定义的边框绘制效果。 switch (uMsg) { case WM_NCPAINT: @@ -1635,19 +1642,25 @@ namespace NppDarkMode return 0; } break; + //以上部分代码使用 GetWindowDC 函数获取窗口的设备上下文,然后根据窗口的样式和状态计算绘制边框所需的相关信息。 + //通过调用 NppDarkMode::paintRoundFrameRect 函数来绘制圆角矩形边框,使用不同的画笔来绘制不同的边框样式。 + //绘制完成后,通过 ReleaseDC 函数释放设备上下文。最后,返回值为 0,表示消息已经被处理完毕。 case WM_NCCALCSIZE: { - if (!NppDarkMode::isEnabled()) + if (!NppDarkMode::isEnabled()) //检查是否启用了 NppDarkMode,如果没有启用,则直接跳过。 { break; } - auto lpRect = reinterpret_cast(lParam); - ::InflateRect(lpRect, -(::GetSystemMetrics(SM_CXEDGE)), -(::GetSystemMetrics(SM_CYEDGE))); + auto lpRect = reinterpret_cast(lParam); //通过将 lParam 强制转换为 LPRECT 类型,获取指向窗口矩形结构的指针。 + ::InflateRect(lpRect, -(::GetSystemMetrics(SM_CXEDGE)), -(::GetSystemMetrics(SM_CYEDGE))); //利用 InflateRect 函数扩展客户区矩形的尺寸,将其减去窗口边框的宽度和高度(使用 SM_CXEDGE 和 SM_CYEDGE 系统度量值)。这样可以得到去除边框后的客户区矩形。 auto style = ::GetWindowLongPtr(hWnd, GWL_STYLE); bool hasVerScrollbar = (style & WS_VSCROLL) == WS_VSCROLL; + + //根据窗口的样式,检查是否有垂直和水平滚动条。如果有垂直滚动条,则将客户区矩形的右边减去垂直滚动条的宽度(使用 SM_CXVSCROLL 系统度量值)。 + //如果有水平滚动条,则将客户区矩形的底部减去水平滚动条的高度(使用 SM_CYHSCROLL 系统度量值)。 if (hasVerScrollbar) { lpRect->right -= ::GetSystemMetrics(SM_CXVSCROLL); @@ -1659,10 +1672,14 @@ namespace NppDarkMode lpRect->bottom -= ::GetSystemMetrics(SM_CYHSCROLL); } - return 0; + return 0; //返回值为 0,表示已经处理完 WM_NCCALCSIZE 消息。 } break; + //在这个代码块中,首先检查是否启用了 NppDarkMode,如果没有启用,则直接跳过。 + //然后,通过调用 GetFocus 函数检查窗口是否具有焦点,如果有焦点则跳过。 + //接下来,创建一个 TRACKMOUSEEVENT 结构体,并设置其中的成员变量。这个结构体用于跟踪鼠标离开窗口的消息。通过调用 TrackMouseEvent 函数,将该结构体传递给系统,以便在鼠标离开窗口时收到 WM_MOUSELEAVE 消息。 + //然后,检查 isHotStatic 变量的值。如果它为假,则将其设置为真,并通过调用 SetWindowPos 函数更新窗口的位置和大小。这里使用了 SWP_NOMOVE、SWP_NOSIZE 和 SWP_NOZORDER 标志,表示不改变窗口的位置、大小和层次关系,只刷新窗口的边框样式(使用 SWP_FRAMECHANGED 标志)。 case WM_MOUSEMOVE: { if (!NppDarkMode::isEnabled()) @@ -1690,6 +1707,10 @@ namespace NppDarkMode } break; + //在这个代码块中,首先检查是否启用了 NppDarkMode,如果没有启用,则直接跳过。 + //然后,检查 isHotStatic 变量的值。如果它为真,则将其设置为假,并通过调用 SetWindowPos 函数更新窗口的位置和大小。 + //接下来,同样创建一个 TRACKMOUSEEVENT 结构体,并设置其中的成员变量。 + //然后,通过调用 TrackMouseEvent 函数,取消对鼠标离开窗口的跟踪,并清除鼠标悬停时间。 case WM_MOUSELEAVE: { if (!NppDarkMode::isEnabled()) @@ -1714,20 +1735,21 @@ namespace NppDarkMode case WM_NCDESTROY: { - RemoveWindowSubclass(hWnd, CustomBorderSubclass, uIdSubclass); + RemoveWindowSubclass(hWnd, CustomBorderSubclass, uIdSubclass); //调用 RemoveWindowSubclass 函数,将窗口子类移除,以确保在窗口销毁时不再收到自定义边框的消息。 } break; } - return DefSubclassProc(hWnd, uMsg, wParam, lParam); + return DefSubclassProc(hWnd, uMsg, wParam, lParam); //通过调用 DefSubclassProc 函数,将消息传递给默认的窗口过程进行处理。 } - void subclassCustomBorderForListBoxAndEditControls(HWND hwnd) + void subclassCustomBorderForListBoxAndEditControls(HWND hwnd) //hwnd为要进行子类化的窗口句柄。 { SetWindowSubclass(hwnd, CustomBorderSubclass, g_customBorderSubclassID, 0); } - constexpr UINT_PTR g_comboBoxSubclassID = 42; + constexpr UINT_PTR g_comboBoxSubclassID = 42; //标识子类化的ID + //子类函数 ComboBoxSubclass,它是一个回调函数,用于处理窗口消息。 LRESULT CALLBACK ComboBoxSubclass( HWND hWnd, UINT uMsg, @@ -1736,6 +1758,7 @@ namespace NppDarkMode UINT_PTR uIdSubclass, DWORD_PTR dwRefData ) + { auto hwndEdit = reinterpret_cast(dwRefData); @@ -1747,25 +1770,32 @@ namespace NppDarkMode { break; } - + //定义一个名为 rc 的 RECT 结构体,并使用 ::GetClientRect 函数获取窗口客户区的矩形区域信息。 RECT rc{}; ::GetClientRect(hWnd, &rc); - + + //定义一个名为 ps 的 PAINTSTRUCT 结构体,并调用 ::BeginPaint 函数开始绘制操作,将得到的设备上下文句柄保存在 hdc 变量中。 PAINTSTRUCT ps{}; auto hdc = ::BeginPaint(hWnd, &ps); + //选择关联字体 ::SelectObject(hdc, reinterpret_cast(::SendMessage(hWnd, WM_GETFONT, 0, 0))); ::SetBkColor(hdc, NppDarkMode::getBackgroundColor()); auto holdBrush = ::SelectObject(hdc, NppDarkMode::getDarkerBackgroundBrush()); auto& dpiManager = NppParameters::getInstance()._dpiManager; - + + //定义一个名为 rcArrow 的 RECT 结构体变量,用于存储组合框箭头的位置和尺寸信息。 RECT rcArrow{}; - + + //定义一个名为 cbi 的 COMBOBOXINFO 结构体,并设置其 cbSize 成员为结构体的大小。 + //然后通过调用 ::GetComboBoxInfo 函数获取与指定组合框窗口相关的信息,并将结果存储在 cbi 变量中。 COMBOBOXINFO cbi{}; cbi.cbSize = sizeof(COMBOBOXINFO); const bool resultCbi = ::GetComboBoxInfo(hWnd, &cbi) != FALSE; + + //根据获取到的组合框信息或者客户区的尺寸,动态地确定箭头区域的位置和尺寸 if (resultCbi) { rcArrow = cbi.rcButton; @@ -1779,12 +1809,16 @@ namespace NppDarkMode }; } - bool hasFocus = false; + bool hasFocus = false; //定义了一个 hasFocus 变量,并且获取了窗口是否启用的状态。 const bool isWindowEnabled = ::IsWindowEnabled(hWnd) == TRUE; // CBS_DROPDOWN text is handled by parent by WM_CTLCOLOREDIT auto style = ::GetWindowLongPtr(hWnd, GWL_STYLE); + + //如果组合框是下拉列表框(CBS_DROPDOWNLIST),则根据获取到的组合框信息或者客户区的尺寸,确定文本背景的矩形区域 rcTextBg,并使用 FillRect 函数擦除文本背景。 + //然后根据当前选中的项来设置文本颜色和背景颜色,并绘制文本到指定的位置上。 + //最后,如果组合框有焦点且未展开下拉列表,则使用 DrawFocusRect 函数绘制焦点矩形框。 if ((style & CBS_DROPDOWNLIST) == CBS_DROPDOWNLIST) { hasFocus = ::GetFocus() == hWnd; @@ -1828,6 +1862,8 @@ namespace NppDarkMode ::DrawFocusRect(hdc, &rcTextBg); } } + + //如果组合框是可编辑的下拉框(CBS_DROPDOWN),则判断编辑框是否拥有焦点,并根据情况设置 hasFocus 变量的值。 else if ((style & CBS_DROPDOWN) == CBS_DROPDOWN && hwndEdit != nullptr) { hasFocus = ::GetFocus() == hwndEdit; @@ -1852,10 +1888,10 @@ namespace NppDarkMode auto holdPen = static_cast(::SelectObject(hdc, hSelectedPen)); POINT edge[] = { - {rcArrow.left - 1, rcArrow.top}, - {rcArrow.left - 1, rcArrow.bottom} + {rcArrow.left - 1, rcArrow.top}, //箭头区域左侧顶部 + {rcArrow.left - 1, rcArrow.bottom} //箭头区域左侧底部 }; - ::Polyline(hdc, edge, _countof(edge)); + ::Polyline(hdc, edge, _countof(edge)); //绘制连线(边框线) int roundCornerValue = NppDarkMode::isWindows11() ? dpiManager.scaleX(4) : 0; NppDarkMode::paintRoundFrameRect(hdc, rc, hSelectedPen, roundCornerValue, roundCornerValue); @@ -1875,7 +1911,10 @@ namespace NppDarkMode } return DefSubclassProc(hWnd, uMsg, wParam, lParam); } + // 以上代码用于自定义列表框和编辑控件的边框和外观,通过调用 SetWindowSubclass 函数将子类函数与窗口句柄关联起来,实现自定义的绘制效果。 + + //给组合框控件设置子类化 void subclassComboBoxControl(HWND hwnd) { DWORD_PTR hwndEditData = 0; diff --git a/src/PowerEditor/src/NppDarkMode.h b/src/PowerEditor/src/NppDarkMode.h index f14abca..63fa7ac 100644 --- a/src/PowerEditor/src/NppDarkMode.h +++ b/src/PowerEditor/src/NppDarkMode.h @@ -20,11 +20,11 @@ #include "Common.h" // for generic_string -namespace NppDarkMode +namespace NppDarkMode //ռNppDarkMode { - struct Colors + struct Colors //Colorsɫṹ { - COLORREF background = 0; + COLORREF background = 0; //COLORREF һ 32-bit ֵһɫ COLORREF softerBackground = 0; COLORREF hotBackground = 0; COLORREF pureBackground = 0; @@ -38,30 +38,30 @@ namespace NppDarkMode COLORREF disabledEdge = 0; }; - struct Options + struct Options //Optionsѡṹ { bool enable = false; bool enableMenubar = false; bool enablePlugin = false; }; - struct NppDarkModeParams + struct NppDarkModeParams //paramsṹ { const wchar_t* _themeClassName = nullptr; bool _subclass = false; bool _theme = false; }; - enum class ToolTipsType + enum class ToolTipsType //ö٣ΪToolTipsType { - tooltip, + tooltip, //dz toolbar, listview, treeview, tabbar }; - enum ColorTone { + enum ColorTone { //ɫ blackTone = 0, redTone = 1, greenTone = 2, @@ -72,14 +72,14 @@ namespace NppDarkMode customizedTone = 32 }; - enum class TreeViewStyle + enum class TreeViewStyle // { classic = 0, light = 1, dark = 2 }; - struct AdvOptDefaults + struct AdvOptDefaults //Ĭѡ { generic_string _xmlFileName; int _toolBarIconSet = -1; @@ -87,7 +87,7 @@ namespace NppDarkMode bool _tabUseTheme = false; }; - struct AdvancedOptions + struct AdvancedOptions //߼ѡ { bool _enableWindowsMode = false; @@ -108,7 +108,7 @@ namespace NppDarkMode bool isWindowsModeEnabled(); void setWindowsMode(bool enable); - generic_string getThemeName(); + generic_string getThemeName(); //generic_string void setThemeName(const generic_string& newThemeName); int getToolBarIconSet(bool useDark); void setToolBarIconSet(int state2Set, bool useDark); @@ -119,7 +119,7 @@ namespace NppDarkMode bool isWindows10(); bool isWindows11(); - DWORD getWindowsBuildNumber(); + DWORD getWindowsBuildNumber(); //DWORD Double Word ÿwordΪ2ֽڵijȣDWORD ˫ּΪ4ֽڣÿֽ8λ32λ COLORREF invertLightness(COLORREF c); COLORREF invertLightnessSofter(COLORREF c); @@ -142,7 +142,7 @@ namespace NppDarkMode COLORREF getHotEdgeColor(); COLORREF getDisabledEdgeColor(); - HBRUSH getBackgroundBrush(); + HBRUSH getBackgroundBrush(); //HBRUSH ȡˢ HBRUSH getDarkerBackgroundBrush(); HBRUSH getSofterBackgroundBrush(); HBRUSH getHotBackgroundBrush(); @@ -152,7 +152,7 @@ namespace NppDarkMode HBRUSH getHotEdgeBrush(); HBRUSH getDisabledEdgeBrush(); - HPEN getDarkerTextPen(); + HPEN getDarkerTextPen(); // HPEN getEdgePen(); HPEN getHotEdgePen(); HPEN getDisabledEdgePen(); @@ -175,12 +175,12 @@ namespace NppDarkMode Colors getDarkModeDefaultColors(); void changeCustomTheme(const Colors& colors); - // handle events + // handle events ¼ void handleSettingChange(HWND hwnd, LPARAM lParam, bool isFromBtn = false); bool isDarkModeReg(); - // processes messages related to UAH / custom menubar drawing. - // return true if handled, false to continue with normal processing in your wndproc + // processes messages related to UAH / custom menubar drawing. Ϣ + // return true if handled, false to continue with normal processing in your wndproc ˷truefalse bool runUAHWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT* lr); void drawUAHMenuNCBottomLine(HWND hWnd); @@ -191,7 +191,7 @@ namespace NppDarkMode bool allowDarkModeForWindow(HWND hWnd, bool allow); void setTitleBarThemeColor(HWND hWnd); - // enhancements to DarkMode.h + // enhancements to DarkMode.h DarkMode.hĸĽ void enableDarkScrollBarForWindowAndChildren(HWND hwnd); inline void paintRoundFrameRect(HDC hdc, const RECT rect, const HPEN hpen, int width = 0, int height = 0); @@ -235,13 +235,13 @@ namespace NppDarkMode bool isThemeDark(); void setBorder(HWND hwnd, bool border = true); - BOOL CALLBACK enumAutocompleteProc(HWND hwnd, LPARAM lParam); + BOOL CALLBACK enumAutocompleteProc(HWND hwnd, LPARAM lParam); //Windows APIеĻصöԶбеHWND hwndԶбĴھ LPARAM lParamûĸӲ void setDarkAutoCompletion(); - LRESULT onCtlColor(HDC hdc); + LRESULT onCtlColor(HDC hdc); //LRESULTһָͣǴӴڳ߻صص32λֵ LRESULT onCtlColorSofter(HDC hdc); LRESULT onCtlColorDarker(HDC hdc); LRESULT onCtlColorError(HDC hdc); LRESULT onCtlColorDarkerBGStaticText(HDC hdc, bool isTextEnabled); - INT_PTR onCtlColorListbox(WPARAM wParam, LPARAM lParam); + INT_PTR onCtlColorListbox(WPARAM wParam, LPARAM lParam); //INT_PTRⶨͣΪ˽32λ64λļԶõĹؼ }