You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windhawk修改窗口关闭按钮颜色失败:多方案尝试无效求助

修改Windows 11关闭按钮悬停颜色失败求助

我尝试通过Windhawk(窗口模组分享平台)修改Windows 11窗口关闭按钮的悬停颜色,先后试过以下方案,但均完全无效:

  • 修改DwmSetWindowAttribute以更改DWMWA_CAPTION_COLOR
  • 挂钩DwmGetWindowAttribute而非DwmSetWindowAttribute
  • 拦截WM_NCPAINT消息自定义绘制关闭按钮
  • 使用窗口子类化创建子窗口的Overlay Button方案

以下是我尝试的Overlay Button方案代码:

// ==WindhawkMod==
// @id              custom-overlay-close-button-mod
// @name            自定义覆盖式关闭按钮模组
// @description     添加可自定义悬停颜色的覆盖式关闭按钮
// @version         2.0.2
// @author          你的名字
// @github          https://github.com/YourName/YourRepo
// @include         *
// @compilerOptions -luser32 -lgdi32 -luxtheme -ldwmapi -lcomctl32
// ==/WindhawkMod==

// ==WindhawkModReadme==
/*
# 自定义覆盖式关闭按钮模组
本模组添加一个可自定义悬停颜色的覆盖式关闭按钮,通过在原有关闭按钮上方创建一个小型子窗口实现。

## 特性
- 可自定义悬停颜色的关闭按钮
- 适用于Windows 11各类应用
- 保留原窗口功能
*/
// ==/WindhawkModReadme==

// ==WindhawkModSettings==
/*
- closeButtonHoverColor: "#FF0000"
  $name: 关闭按钮悬停颜色
  $description: 鼠标悬停时显示的颜色(例如#FF0000为红色)
- enableMod: true
  $name: 启用模组
  $description: 开关模组的启用状态
*/
// ==/WindhawkModSettings==

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <dwmapi.h>
#include <commctrl.h>

// 函数声明
static LRESULT CALLBACK HostWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
static LRESULT CALLBACK CloseButtonWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static void PositionCloseButton(HWND hwndHost, HWND hwndButton);
static COLORREF HexToColorRef(const wchar_t* hexColor);

// 全局变量
static COLORREF g_closeButtonHoverColor;
static bool g_enableMod;
static HBRUSH g_hoverBrush = NULL;

// Windhawk模组函数
void LoadSettings() {
    g_closeButtonHoverColor = HexToColorRef(Wh_GetStringSetting(L"closeButtonHoverColor"));
    g_enableMod = Wh_GetIntSetting(L"enableMod") != 0;
    if (g_hoverBrush) DeleteObject(g_hoverBrush);
    g_hoverBrush = CreateSolidBrush(g_closeButtonHoverColor);
    Wh_Log(L"已加载设置:悬停颜色=%06X,启用状态=%d", g_closeButtonHoverColor, g_enableMod);
}

BOOL Wh_ModInit() {
    LoadSettings();
    // 初始化通用控件
    INITCOMMONCONTROLSEX icex;
    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
    icex.dwICC = ICC_STANDARD_CLASSES;
    InitCommonControlsEx(&icex);
    return TRUE;
}

void Wh_ModUninit() {
    if (g_hoverBrush) DeleteObject(g_hoverBrush);
}

void Wh_ModSettingsChanged() {
    LoadSettings();
}

// 辅助函数:十六进制颜色转COLORREF
static COLORREF HexToColorRef(const wchar_t* hexColor) {
    unsigned int color = wcstoul(hexColor + 1, NULL, 16);
    return RGB((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF);
}

// 辅助函数:定位关闭按钮位置
static void PositionCloseButton(HWND hwndHost, HWND hwndButton) {
    RECT rcClient;
    GetClientRect(hwndHost, &rcClient);
    
    POINT ptTopRight = { rcClient.right, rcClient.top };
    ClientToScreen(hwndHost, &ptTopRight);
    
    int buttonSize = GetSystemMetrics(SM_CXSIZE);
    SetWindowPos(hwndButton, NULL, 
                 ptTopRight.x - buttonSize, ptTopRight.y, 
                 buttonSize, buttonSize, 
                 SWP_NOZORDER | SWP_NOACTIVATE);
}

// 宿主窗口子类化过程
static LRESULT CALLBACK HostWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
    HWND hwndButton = (HWND)dwRefData;

    switch (uMsg) {
        case WM_SIZE:
        case WM_MOVE:
            if (hwndButton) {
                PositionCloseButton(hwnd, hwndButton);
            }
            break;
        case WM_DESTROY:
            if (hwndButton) {
                DestroyWindow(hwndButton);
            }
            RemoveWindowSubclass(hwnd, HostWndProc, uIdSubclass);
            break;
    }

    return DefSubclassProc(hwnd, uMsg, wParam, lParam);
}

// 自定义关闭按钮窗口过程
static LRESULT CALLBACK CloseButtonWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    static bool isHovered = false;
    static bool isPressed = false;

    switch (uMsg) {
        case WM_PAINT: {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);
            
            RECT rc;
            GetClientRect(hwnd, &rc);
            
            if (isHovered) {
                FillRect(hdc, &rc, g_hoverBrush);
            }
            
            // 绘制叉号
            HPEN hPen = CreatePen(PS_SOLID, 2, isHovered ? RGB(255, 255, 255) : RGB(0, 0, 0));
            HGDIOBJ hOldPen = SelectObject(hdc, hPen);
            
            MoveToEx(hdc, rc.left + 5, rc.top + 5, NULL);
            LineTo(hdc, rc.right - 5, rc.bottom - 5);
            MoveToEx(hdc, rc.right - 5, rc.top + 5, NULL);
            LineTo(hdc, rc.left + 5, rc.bottom - 5);
            
            SelectObject(hdc, hOldPen);
            DeleteObject(hPen);
            
            EndPaint(hwnd, &ps);
            return 0;
        }
        case WM_MOUSEMOVE:
            if (!isHovered) {
                isHovered = true;
                InvalidateRect(hwnd, NULL, TRUE);
                TRACKMOUSEEVENT tme = { sizeof(TRACKMOUSEEVENT), TME_LEAVE, hwnd, 0 };
                TrackMouseEvent(&tme);
            }
            return 0;
        case WM_MOUSELEAVE:
            isHovered = false;
            InvalidateRect(hwnd, NULL, TRUE);
            return 0;
        case WM_LBUTTONDOWN:
            isPressed = true;
            SetCapture(hwnd);
            return 0;
        case WM_LBUTTONUP:
            if (isPressed) {
                HWND hwndParent = GetParent(hwnd);
                if (hwndParent) {
                    PostMessage(hwndParent, WM_CLOSE, 0, 0);
                }
            }
            isPressed = false;
            ReleaseCapture();
            return 0;
    }

    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

// 窗口创建后钩子:添加自定义关闭按钮
void Wh_ModAfterCreateWindow(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT result) {
    if (!g_enableMod) return;

    WCHAR className[256];
    if (GetClassName(hwnd, className, ARRAYSIZE(className)) == 0) return;

    // 仅处理顶级窗口(排除对话框类#32770)
    if (wcscmp(className, L"#32770") != 0 && GetWindow(hwnd, GW_OWNER) == NULL) {
        HWND hwndButton = CreateWindowEx(
            WS_EX_TOPMOST | WS_EX_LAYERED,
            L"BUTTON", L"",
            WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
            0, 0, 0, 0, hwnd, NULL, NULL, NULL);

        if (hwndButton) {
            SetWindowLongPtr(hwndButton, GWLP_WNDPROC, (LONG_PTR)CloseButtonWndProc);
            SetLayeredWindowAttributes(hwndButton, RGB(255, 0, 255), 0, LWA_COLORKEY);
            PositionCloseButton(hwnd, hwndButton);
            SetWindowSubclass(hwnd, HostWndProc, 0, (DWORD_PTR)hwndButton);
            Wh_Log(L"已为窗口添加自定义关闭按钮:%p", hwnd);
        }
    }
}

内容的提问来源于stack exchange,提问作者Kai Piper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 06:25:55