【问题标题】:WinAPI, TreeView: a gray item by TVIS_CUTWinAPI,TreeView:TVIS_CUT 的灰色项目
【发布时间】:2020-12-15 16:13:45
【问题描述】:

我想将一个项目设为灰色。根据docs,我在stateMaskmask中设置了TVIS_CUT
但它不起作用(该项目像往常一样是黑色的)。 TVIS_BOLD 完美运行。

我使用 CodeBlocks17 (gcc)/Win7x64。我还尝试了 VS2005 和另一个操作系统 (WinXP),结果相同。
我错过了什么?

#define _UNICODE
#define UNICODE

#include <windows.h>
#include <commctrl.h>

LRESULT CALLBACK cbMain (HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow) {
    MSG msg;
    WNDCLASSEX wc{0};

    wc.hInstance = hInstance;
    wc.lpszClassName = TEXT("MyAppClass");
    wc.lpfnWndProc = cbMain;
    wc.style = CS_DBLCLKS;
    wc.cbSize = sizeof (WNDCLASSEX);
    wc.hIcon = LoadIcon(0, IDC_ICON);
    wc.hCursor = LoadCursor (NULL, IDC_ARROW);
    wc.lpszMenuName = 0;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    if (!RegisterClassEx (&wc))
        return EXIT_FAILURE;

    HWND hMainWnd = CreateWindowEx (0, TEXT("MyAppClass"), NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 500, 600, 160, 300, HWND_DESKTOP, NULL, hInstance, NULL);
    HWND hTreeWnd = CreateWindowEx(0, WC_TREEVIEW, NULL, WS_VISIBLE | WS_CHILD | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT  | TVS_EDITLABELS, 0, 0, 150, 200, hMainWnd, (HMENU)100, hInstance,  NULL);

    TVITEM tvi{0};
    tvi.mask = TVIF_TEXT | TVIF_STATE;
    tvi.pszText = TEXT("Item");
    tvi.cchTextMax = 40;
    tvi.stateMask = TVIS_CUT;
    tvi.state = TVIS_CUT;

    TVINSERTSTRUCT tvins{0};
    tvins.item = tvi;
    tvins.hInsertAfter = TVI_ROOT;
    tvins.hParent = TVI_ROOT;
    SendMessage(hTreeWnd, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);

    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

LRESULT CALLBACK cbMain (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
        case WM_DESTROY:
            PostQuitMessage (0);
            break;

        default:
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}

【问题讨论】:

  • TVIS_CUT 将重影(淡出)图标,但不会更改文本颜色。为此,您需要使用Custom Draw
  • 以下代码示例将树视图项设置为禁用状态:m_treeCtrl.SetItemStateEx(hPA, TVIS_EX_DISABLED); 你可以检查它是否有帮助。
  • @Jonathan Potter,谢谢。我检查了它,是的,它的图标可以工作。但我不使用图标。
  • @Rita Han - MSFT,这是一种 MFC 方式。纯WinAPI没有这个方法和TVIS_EX_DISABLED常量。

标签: c winapi treeview


【解决方案1】:

正如乔纳森·波特所说,我使用了Custom Draw

这里有一个陷阱:当当前项目发生变化时,旧项目在pCustomDraw-&gt;nmcd.uItemState 成员中有CDIS_FOCUSCDIS_SELECTED 标志,而新项目没有。所以pCustomDraw-&gt;clrText = (pNMTVCD-&gt;nmcd.uItemState &amp; CDIS_FOCUS) == CDIS_FOCUS) ? ... 会有点奇怪。我改为检查pCustomDraw-&gt;clrTextBk。但是当用户使用自定义主题时,它可能会被破坏。

我使用this article 和应用code 来构建示例。

#define _UNICODE
#define UNICODE
#define _WIN32_WINNT 0x0501
#define _WIN32_IE 0x0500

#include <windows.h>
#include <commctrl.h>

#define IDC_TREEVIEW 100

LRESULT CALLBACK cbMain (HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow) {
    MSG msg;
    WNDCLASSEX wc{0};

    wc.hInstance = hInstance;
    wc.lpszClassName = TEXT("MyAppClass");
    wc.lpfnWndProc = cbMain;
    wc.style = CS_DBLCLKS;
    wc.cbSize = sizeof (WNDCLASSEX);
    wc.hIcon = LoadIcon(0, IDC_ICON);
    wc.hCursor = LoadCursor (NULL, IDC_ARROW);
    wc.lpszMenuName = 0;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    if (!RegisterClassEx (&wc))
        return EXIT_FAILURE;

    HWND hMainWnd = CreateWindowEx (0, TEXT("MyAppClass"), NULL, WS_OVERLAPPED | WS_VISIBLE | WS_SYSMENU, 500, 600, 160, 300, HWND_DESKTOP, NULL, hInstance, NULL);
    HWND hTreeWnd = CreateWindowEx(0, WC_TREEVIEW, NULL, WS_VISIBLE | WS_CHILD | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT  | TVS_EDITLABELS, 0, 0, 150, 200, hMainWnd, (HMENU)IDC_TREEVIEW, hInstance,  NULL);

    TVITEM tvi{0};
    TVINSERTSTRUCT tvins{0};
    tvi.mask = TVIF_TEXT | TVIF_STATE;
    tvi.pszText = TEXT("Item1");
    tvi.cchTextMax = 40;
    tvi.stateMask = 0;
    tvi.state = 0;

    tvins.item = tvi;
    tvins.hInsertAfter = TVI_ROOT;
    tvins.hParent = TVI_ROOT;
    SendMessage(hTreeWnd, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);

    tvi.pszText = TEXT("Item2");
    tvins.item = tvi;
    SendMessage(hTreeWnd, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);

    tvi.stateMask = TVIS_CUT;
    tvi.state = TVIS_CUT;
    tvi.pszText = TEXT("Item3");
    tvins.item = tvi;
    SendMessage(hTreeWnd, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);

    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

LRESULT CALLBACK cbMain (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
        case WM_DESTROY: {
            PostQuitMessage (0);
        }
        break;

        case WM_NOTIFY: {
            NMHDR* pHdr = (LPNMHDR)lParam;
            if (pHdr->idFrom == IDC_TREEVIEW && pHdr->code == NM_CUSTOMDRAW) {
                LPNMTVCUSTOMDRAW pCustomDraw = (LPNMTVCUSTOMDRAW)lParam;
                if (pCustomDraw->nmcd.dwDrawStage == CDDS_PREPAINT)
                    return CDRF_NOTIFYITEMDRAW;

                if (pCustomDraw->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) {
                    BOOL isCut = TreeView_GetItemState(pHdr->hwndFrom, (HTREEITEM)pCustomDraw->nmcd.dwItemSpec, TVIS_CUT) & TVIS_CUT;
                    pCustomDraw->clrText = pCustomDraw->clrTextBk != RGB( 255, 255, 255) ? RGB( 255, 255, 255) :
                        isCut ? RGB( 128, 128, 128 ) : RGB( 0, 0, 0);
                }

                return CDRF_DODEFAULT;
            }
        }
        break;

        default:
            return DefWindowProc (hWnd, message, wParam, lParam);
    }

    return 0;
}

【讨论】:

    猜你喜欢
    • 2020-10-28
    • 2010-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-28
    • 2011-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多