树形视图更改项目图像的颜色

时间:2018-11-23 05:15:13

标签: c winapi

因此,我一直试图将图像添加到WinAPI TreeView通用控件项中。但是,我遇到了真正困扰我的事情,我不知道为什么会发生。由于某些原因,TreeView中的Image的颜色与实际位图的颜色不同。我拍摄了一个测试程序的屏幕截图,该程序绘制了一个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;

}

1 个答案:

答案 0 :(得分:0)

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

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

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