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

如何修改Win32 ListView控件的滚动条颜色?

解决Win32 ListView滚动条在深色主题下显示异常的问题

问题背景

自定义Win32 ListView控件时,已将背景改为深色,但滚动条仍显示为白色,不符合需求。尝试子类化ListView并处理WM_CTLCOLORSCROLLBAR消息无效——子类化本身有效(已通过WM_NCPAINT验证),但该消息无作用,新建干净项目测试问题依旧。

原因分析

  1. 消息接收对象错误:WM_CTLCOLORSCROLLBAR消息是发送给控件的父窗口,而非控件自身。因此子类化ListView无法捕获该消息,必须在主窗口的窗口过程中处理。
  2. 主题样式干扰:若通过manifest启用了ComCtl32 v6主题,系统会优先使用主题样式绘制滚动条,可能覆盖WM_CTLCOLORSCROLLBAR的颜色设置。

解决方案

方案1:主窗口处理WM_CTLCOLORSCROLLBAR

在主窗口的WndProc中捕获消息,判断滚动条所属控件为目标ListView后,设置滚动条颜色。

方案2:禁用ListView主题(可选)

通过SetWindowTheme禁用ListView的主题样式,避免主题覆盖自定义颜色设置。

方案3:子类化手动绘制滚动条(灵活定制)

子类化ListView后处理WM_NCPAINT消息,完全手动绘制滚动条外观,实现高度自定义。

修改后的示例代码

#include <Windows.h>
#include <CommCtrl.h>
#include <string>
#include <iostream>

#pragma comment(lib, "Comctl32.lib")

#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

bool isRunning = false;
int exitCode = 0;

HFONT listViewFont;
HWND g_hListView = NULL; // 全局变量保存ListView句柄,用于判断滚动条归属

LRESULT CALLBACK ListViewProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR idSubclass, DWORD_PTR dwRefData) {
    switch (msg) {
        // 可选:验证子类化生效的代码(绘制红色边框)
        case WM_NCPAINT: {
            LRESULT result = DefSubclassProc(hwnd, msg, wParam, lParam);
            HDC hdc = GetWindowDC(hwnd);
            RECT rc;
            GetWindowRect(hwnd, &rc);
            HBRUSH brush = CreateSolidBrush(RGB(255,0,0));
            FrameRect(hdc, &rc, brush);
            DeleteObject(brush);
            ReleaseDC(hwnd, hdc);
            return result;
        } break;
        default:
            return DefSubclassProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
        case WM_CREATE: {
            g_hListView = CreateWindowA("SysListView32", "", WS_CHILD | LVS_REPORT | LVS_NOCOLUMNHEADER, 50, 50, 250, 20 * 20, hWnd, NULL, NULL, NULL);
            SetWindowSubclass(g_hListView, ListViewProc, 0, 0);
            ListView_SetBkColor(g_hListView, RGB(51, 51, 51));
            ListView_SetTextColor(g_hListView, RGB(255,255,255)); // 适配深色背景的文字颜色
            ListView_SetExtendedListViewStyle(g_hListView, LVS_EX_FULLROWSELECT);
            SendMessageA(g_hListView, WM_SETFONT, (WPARAM)listViewFont, NULL);
            
            // 禁用ListView主题,避免样式覆盖自定义设置
            SetWindowTheme(g_hListView, L"", L"");
            
            ShowWindow(g_hListView, true);
            UpdateWindow(g_hListView);

            LVCOLUMN column;
            column.mask = LVCF_WIDTH | LVCF_TEXT;
            column.pszText = (LPWSTR)L"Column";
            column.cx = 250;
            ListView_InsertColumn(g_hListView, 0, &column);

            for (size_t i = 0; i < 50; i++) {
                LVITEM item;
                item.pszText = (LPWSTR)L"item";
                item.mask = LVIF_TEXT;
                item.iItem = i;
                item.iSubItem = 0;
                ListView_InsertItem(g_hListView, &item);
            };
        } break;
        case WM_CTLCOLORSCROLLBAR: {
            HWND hCtrl = (HWND)lParam;
            // 判断滚动条属于目标ListView
            if (hCtrl == g_hListView) {
                HDC hdc = (HDC)wParam;
                SetBkColor(hdc, RGB(51,51,51));
                // 返回用于绘制滚动条背景的画刷
                return (LRESULT)CreateSolidBrush(RGB(51,51,51));
            }
            return DefWindowProcA(hWnd, msg, wParam, lParam);
        } break;
        case WM_CLOSE: {
            isRunning = false;
            PostQuitMessage(exitCode);
        } break;
        default: {
            return DefWindowProcA(hWnd, msg, wParam, lParam);
        } break;
    };
    return DefWindowProcA(hWnd, msg, wParam, lParam);
};

void InitFonts() {
    listViewFont = CreateFontA(
        16, 
        0, 0, 0, 
        FW_NORMAL, 
        FALSE, 
        FALSE, 
        FALSE, 
        DEFAULT_CHARSET,
        OUT_DEFAULT_PRECIS,
        CLIP_DEFAULT_PRECIS,
        DEFAULT_QUALITY,
        DEFAULT_PITCH | FF_DONTCARE,
        "Georgia"
    );
};

int main() {
    InitFonts();

    WNDCLASSEXA wc = { 0 };
    wc.cbSize = sizeof(WNDCLASSEXA);
    wc.hbrBackground = CreateSolidBrush(RGB(255, 255, 255));
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.lpszClassName = "_MainWindow";
    wc.lpfnWndProc = WndProc;

    RegisterClassExA(&wc);

    HWND hWnd = CreateWindowExA(WS_EX_OVERLAPPEDWINDOW, "_MainWindow", "", WS_OVERLAPPEDWINDOW, 500, 200, 500, 500, NULL, NULL, NULL, NULL);
    ShowWindow(hWnd, true);
    UpdateWindow(hWnd);

    isRunning = true;

    MSG msg;
    while (isRunning) {
        if (GetMessageA(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessageA(&msg);
        };
    };

    // 清理资源
    DeleteObject(listViewFont);
    RemoveWindowSubclass(g_hListView, ListViewProc, 0);

    return exitCode;
}

关键修改点

  • 添加全局变量g_hListView,用于在主窗口判断滚动条所属控件。
  • 在主窗口WndProc中处理WM_CTLCOLORSCROLLBAR消息,针对目标ListView设置滚动条背景色。
  • 调用SetWindowTheme禁用ListView主题,避免样式冲突。
  • 添加文字颜色设置,适配深色背景。
  • 补充资源清理代码,避免内存泄漏。

内容的提问来源于stack exchange,提问作者Erkan Demirci

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 17:19:50