c - TreeView 更改项目图像的颜色

标签 c winapi

所以我一直在尝试将图像添加到我的 WinAPI TreeView 公共(public)控件项中。然而,我遇到了一些真正困扰我的事情,我不知道为什么会这样。由于某种原因,TreeView 中的图像与实际位图中的颜色不同。我截取了我制作的测试程序的屏幕截图,该程序绘制 BMP 图像文件及其对应的 TreeView 文件。 (这是完全相同的图像,但两张图产生不同的结果)。

Window Screenshot

如您所见,左边的图像是它应该看起来的样子,右边的图像是 TreeView 正在绘制的。这只是 TreeView 的工作方式还是什么?或者我的代码中有什么地方做错了吗?如果有人能指出这一点,我将不胜感激,因为出于个人品味,TreeView 图像看起来很恶心,我希望 TreeView 控件能够正确绘制我的图像:P

以下是我用来创建 TreeView 的代码:

    //Load image from relative file path
    g_hBmp = LoadImage(GetModuleHandle(NULL), "image.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE);

    //Create Treeview
    HWND treeview = CreateWindowEx(0, WC_TREEVIEW, NULL,
        WS_VISIBLE | WS_CHILD | TVS_FULLROWSELECT,
        250, 100, 500, 300,
    hwnd, NULL, GetModuleHandle(NULL), NULL);

    //Add single treeview item
    TVITEM tvi = {0};
    TVINSERTSTRUCT tvins = {0};

    HIMAGELIST himl = NULL;
    himl = ImageList_Create(90, 90, 0, 1, 0);
    int image = ImageList_Add(himl, g_hBmp, NULL);

    SendMessage(treeview, TVM_SETIMAGELIST, (WPARAM) TVSIL_NORMAL, (LPARAM) himl);

    tvi.mask = TVIF_TEXT | TVIF_IMAGE;

    //Set Text
    tvi.pszText = "Some Item";
    tvi.cchTextMax = sizeof("Some Item") - 1;
    tvi.iImage = image;

    tvins.item = tvi;
    tvins.hInsertAfter = TVI_FIRST;
    SendMessage(treeview, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT) &tvins);

这是我的完整代码,以备您复制:

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

HBITMAP g_hBmp = NULL;

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {

        case WM_CREATE: {

            //Load Image
            g_hBmp = LoadImage(GetModuleHandle(NULL), "image.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE);

            //Create Treeview
            HWND treeview = CreateWindowEx(0, WC_TREEVIEW, NULL,
                WS_VISIBLE | WS_CHILD | TVS_FULLROWSELECT,
                250, 100, 500, 300,
            hwnd, NULL, GetModuleHandle(NULL), NULL);

            //Add single treeview item
            TVITEM tvi = {0};
            TVINSERTSTRUCT tvins = {0};

            HIMAGELIST himl = NULL;
            himl = ImageList_Create(90, 90, 0, 1, 0);
            int image = ImageList_Add(himl, g_hBmp, NULL);

            SendMessage(treeview, TVM_SETIMAGELIST, (WPARAM) TVSIL_NORMAL, (LPARAM) himl);

            tvi.mask = TVIF_TEXT | TVIF_IMAGE;

            //Set Text
            tvi.pszText = "Some Item";
            tvi.cchTextMax = sizeof("Some Item") - 1;
            tvi.iImage = image;

            tvins.item = tvi;
            tvins.hInsertAfter = TVI_FIRST;
            SendMessage(treeview, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT) &tvins);

            break;

        }
        case WM_PAINT: {

            PAINTSTRUCT ps = {0};

            //Setup
            HDC hdc = BeginPaint(hwnd, &ps);
            HDC hdcPaint = CreateCompatibleDC(hdc);

            HBITMAP hBmpOld = (HBITMAP) SelectObject(hdcPaint, g_hBmp);

            //Painting
            BitBlt(hdc, 100, 100, 90, 90, hdcPaint, 0, 0, SRCCOPY);

            //Cleanup
            SelectObject(hdcPaint, hBmpOld);
            DeleteDC(hdcPaint);

            EndPaint(hwnd, &ps);
            break;

        }
        case WM_DESTROY: {

            DeleteObject(g_hBmp);
            PostQuitMessage(0);
            break;

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

    }

    return 0;

}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {

    InitCommonControls();

    HWND hwnd = NULL;
    WNDCLASSEX wc = {0};

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    wc.hInstance = hInstance;
    wc.hbrBackground = (HBRUSH) COLOR_WINDOW;
    wc.lpfnWndProc = WndProc;
    wc.lpszClassName = "Parent Window";
    wc.style = CS_VREDRAW | CS_HREDRAW;

    RegisterClassEx(&wc);

    hwnd = CreateWindowEx(0, wc.lpszClassName, "Render Window",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 1000, 1000 / 16 * 9,
    NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd, nShowCmd);
    UpdateWindow(hwnd);

    MSG msg = {0};
    while (GetMessage(&msg, NULL, 0, 0) > 0) {

        TranslateMessage(&msg);
        DispatchMessage(&msg);

    }

    return msg.wParam;

}

最佳答案

正如“Swordfish”在上面提到的,我缺少的是调用 ImageList_Create() 函数时的正确标志。正如您在调用 ImageList_Create(90, 90, 0, 1, 0); 时看到的那样,我将“0”指定为第三个参数(代表 Image List Creation Flag )。如文档中所述,ILC_COLOR 标志的值为零;设置此标志后,它使用通常为 ILC_COLOR4 的“默认行为”(即每个 channel 4 位)。

要解决此问题,我需要做的就是使用 ILC_COLOR24 标志调用该函数,表明我的图像具有 24 位深度。

ImageList_Create(90, 90, ILC_COLOR24, 1, 0);

关于c - TreeView 更改项目图像的颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53440960/

相关文章:

c - 如何打印某个字符和空格后的字符

c - 用新字符串替换字符串模式

我可以确定在使用 MSG_PEEK 成功调用 recv 后立即执行的 UDP recv 不会阻塞吗?

excel - 显示带有超时值的消息框

Python更改屏幕分辨率虚拟机

c - 重新分配数组的大小没有给我任何改变

c - 为什么在字体对话框中不显示 SYSTEM_FONT 的字体大小?

c++ - 如果我两次 ReleaseMutex() 会发生什么?

c++ - 我想复制 (wchar_t *)buffer 中的数据,但我无法这样做,因为还有其他不兼容的类型,类型转换但没有得到结果?

c - (ab) 使用 C 预处理器的合法用途?