如何更改ListView的边框颜色

3

我使用win32 api创建了一个列表视图。

InitCommonControls();
HWND hwndList1 = CreateWindow(WC_LISTVIEW , L"", WS_VISIBLE|WS_CHILD | LVS_REPORT | LVS_EDITLABELS |  LVS_ICON  | LV_VIEW_TILE |  LVS_EX_GRIDLINES | WS_BORDER | LVS_EX_FULLROWSELECT | ES_LEFT , 10, 10, 300, 190, hwnd, NULL, GetModuleHandle(NULL), 0); 

SendMessageW( hwndList1,
            LVM_SETEXTENDEDLISTVIEWSTYLE,
            LVS_EX_FULLROWSELECT ,
            LVS_EX_FULLROWSELECT );



CreateItem(hwndList1 , (char*)L"fault RS458");
CreateItem(hwndList1 , (char*)L"fault RS455");
CreateColumn(hwndList1 , 0 , (char*)L"Insert column" , 300);

我看到列表视图周围有一个黑色边框,如何更改其颜色?


1
尝试移除 WS_BORDER 样式。此外,可以在此处查看微软的示例:https://learn.microsoft.com/en-us/windows/win32/controls/create-a-list-view-control - Richard Critten
1
@Jesper Juhl 我使用Win32 API创建了它...我编辑了我的问题。 - Code-Lover
1
我认为WS_BORDER会使用系统颜色,所以最简单的方法是子类化并自己处理WM_NCPAINT来覆盖它。 - bunglehead
@Code-Lover 基本上你需要创建一个窗口,并覆盖它的窗口过程,使用你自己的方式处理 WM_NCPAINT。你当然可以为此创建一个新类,但这并不是必要的。 - bunglehead
2
顺便提一下,您正在使用错误的样式标志。 LV_VIEW_TILE 只能通过发送 LVM_SETVIEW 消息来设置。对于 LVS_EX_* 标志,您必须发送 LVM_SETEXTENDEDLISTVIEWSTYLE。最后,ES_LEFT 根本与列表视图无关,它属于编辑控件。 - zett42
显示剩余2条评论
1个回答

3

您可以使用SetWindowSubclass(需要comctl32.lib)对窗口进行子类化并处理WM_NCPAINT以绘制控件的非客户区,具体如下:

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

LRESULT CALLBACK ListViewProc(HWND hwnd, 
    UINT msg, WPARAM wp, LPARAM lp, UINT_PTR, DWORD_PTR)
{
    switch(msg)
    {
    case WM_NCPAINT:
    {
        RECT rc;
        GetWindowRect(hwnd, &rc);
        OffsetRect(&rc, -rc.left, -rc.top);
        auto hdc = GetWindowDC(hwnd);
        auto hpen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
        auto oldpen = SelectObject(hdc, hpen);
        SelectObject(hdc, GetStockObject(NULL_BRUSH));
        Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);//draw red frame
        SelectObject(hdc, oldpen);
        DeleteObject(oldpen);
        ReleaseDC(hwnd, hdc);

        //*** EDIT
        //documentation says we should return 0
        //but that causes problem with vertical scrollbar
        //maybe we should break for this subclass case

        break; //not return 0!
    }

    case WM_NCDESTROY:
        RemoveWindowSubclass(hwnd, ListViewProc, 0);
        break;
    }

    return DefSubclassProc(hwnd, msg, wp, lp);
}
...
HWND hwndList1 = CreateWindow(...); 
SetWindowSubclass(hwndList1, ListViewProc, 0, NULL);
补充一下,(char*)L"text" 没有意义。建议使用 ANSI 格式 ((char*)"text") 或 Unicode 格式 ((wchar_t*)L"text",建议使用),并且你可以将 CreateItem 更改为接受 const wchar_t*,然后在最后一步将其转换为 (wchar_t*) 以避免错误。

编辑
WM_NCPAINT 将会中断,不返回零。


请问我应该在哪个过程中处理哪些消息,以便从标题中移除3D边框?谢谢。 - Code-Lover
1
你应该编辑问题并添加一些图片来展示你想要的内容。Listview控件有自己的标题控件,你可能需要对该控件进行子类化。顺便问一下,你启用了“现代UI”吗?查看此帖子以启用视觉样式 - Barmak Shemirani
1
看起来您使用的是默认设置。所有控件都拥有老旧的 3D 外观,这已经过时很多年了。您需要启用可视化样式。然后您的列表视图、按钮、复选框等将会像 Windows 资源管理器中的那些一样。请查看之前的评论。您是否使用 Visual Studio?如果没有,您必须在 *.rc 资源文件中包含一个清单文件 1 24 "myapplication.exe.manifest" - Barmak Shemirani
当我启用视觉样式时,3D边框被移除,但自定义绘制中指定的背景颜色和文本颜色不再应用。是否有一种方法可以在使用视觉样式时更改标题的背景和文本颜色? - Code-Lover
1
使用 HWND hHeader = ListView_GetHeader(hListView) 获取标题控件。如果您想要将单个控件恢复为旧的3D外观,请使用 SetWindowTheme(hHeader, L"", L"");。然后使用“所有者绘制”(而不是“自定义绘制”)进行重绘。我在这篇帖子中展示了如何使用“自定义绘制”。我对您所处的位置感到困惑。您应该发布一个新问题。 - Barmak Shemirani
你应该返回0来表明你已经完全处理了这条消息。 - user13947194

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接