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

Win32 ListView无法分配不同图标:所有项仅显示单个图标

Win32 ListView 不同项显示不同图标的可运行实现(MinGW适配)

完整可运行代码

1. 资源文件定义

resource.h

#define IDI_FEMALE 101
#define IDI_MALE 102
#define IDI_NETWORK 103

resource.rc

#include "resource.h"

IDI_FEMALE ICON "female.ico"
IDI_MALE ICON "male.ico"
IDI_NETWORK ICON "network.ico"

注意:将对应的ico文件放在源码同目录,或修改路径为实际文件位置

2. 主程序代码(main.c)

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

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

#define LISTVIEW_ID 1001

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

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    WNDCLASSEX wc = {0};
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc   = WndProc;
    wc.hInstance     = hInstance;
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszClassName = "ListViewIconDemo";

    if(!RegisterClassEx(&wc)) {
        MessageBox(NULL, "窗口类注册失败!", "错误", MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    HWND hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        "ListViewIconDemo",
        "ListView 多图标演示",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 600, 400,
        NULL, NULL, hInstance, NULL);

    if(hwnd == NULL) {
        MessageBox(NULL, "窗口创建失败!", "错误", MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    MSG msg;
    while(GetMessage(&msg, NULL, 0, 0) > 0) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    static HWND hListView;
    static HIMAGELIST hImageList;
    HINSTANCE hInstance = GetModuleHandle(NULL);

    switch(msg) {
        case WM_CREATE:
            // 初始化通用控件
            INITCOMMONCONTROLSEX icex;
            icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
            icex.dwICC = ICC_LISTVIEW_CLASSES;
            InitCommonControlsEx(&icex);

            // 创建ListView控件
            hListView = CreateWindow(WC_LISTVIEW, "",
                WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS,
                10, 10, 560, 340,
                hwnd, (HMENU)LISTVIEW_ID, hInstance, NULL);

            // 创建ImageList(16x16图标,对应小图标模式)
            hImageList = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 3, 0);
            if(hImageList == NULL) {
                MessageBox(hwnd, "ImageList创建失败!", "错误", MB_ICONERROR);
                break;
            }

            // 加载图标并添加到ImageList,保存每个图标的索引
            int idxFemale = ImageList_AddIcon(hImageList, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_FEMALE)));
            int idxMale = ImageList_AddIcon(hImageList, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MALE)));
            int idxNetwork = ImageList_AddIcon(hImageList, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_NETWORK)));

            // 检查图标是否成功加载
            if(idxFemale == -1 || idxMale == -1 || idxNetwork == -1) {
                MessageBox(hwnd, "图标加载失败!", "错误", MB_ICONERROR);
                ImageList_Destroy(hImageList);
                break;
            }

            // 给ListView设置ImageList(小图标模式,对应列表项的iImage)
            ListView_SetImageList(hListView, hImageList, LVSIL_SMALL);

            // 添加ListView列
            LVCOLUMN lvc = {0};
            lvc.mask = LVCF_TEXT | LVCF_WIDTH;
            lvc.cx = 200;
            lvc.pszText = "名称";
            ListView_InsertColumn(hListView, 0, &lvc);
            lvc.cx = 150;
            lvc.pszText = "类型";
            ListView_InsertColumn(hListView, 1, &lvc);

            // 添加列表项,每个项指定不同的图标索引
            LVITEM lvi = {0};
            lvi.mask = LVIF_TEXT | LVIF_IMAGE;

            // 第一项:女性图标
            lvi.iItem = 0;
            lvi.iSubItem = 0;
            lvi.pszText = "张三";
            lvi.iImage = idxFemale;
            ListView_InsertItem(hListView, &lvi);
            ListView_SetItemText(hListView, 0, 1, "用户");

            // 第二项:男性图标
            lvi.iItem = 1;
            lvi.pszText = "李四";
            lvi.iImage = idxMale;
            ListView_InsertItem(hListView, &lvi);
            ListView_SetItemText(hListView, 1, 1, "用户");

            // 第三项:网络图标
            lvi.iItem = 2;
            lvi.pszText = "云服务器";
            lvi.iImage = idxNetwork;
            ListView_InsertItem(hListView, &lvi);
            ListView_SetItemText(hListView, 2, 1, "设备");
            break;

        case WM_DESTROY:
            ImageList_Destroy(hImageList);
            PostQuitMessage(0);
            break;

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

编译命令(MinGW)

在命令行执行以下步骤:

  1. 编译资源文件:windres resource.rc -o resource.o
  2. 编译主程序并链接:g++ main.c resource.o -o ListViewIconDemo.exe -lcomctl32

关键问题排查与解释

1. 你之前遇到的共性错误

  • 图标索引混淆:直接用资源ID(比如IDI_FEMALE的101)作为LVITEM.iImage的值,而不是用ImageList_AddIcon返回的ImageList内部索引,导致所有项默认显示索引0的图标。
  • ImageList模式不匹配:设置ListView的ImageList时未指定LVSIL_SMALL或LVSIL_NORMAL,导致图标无法关联到列表项。
  • MinGW资源加载疏漏:未用MAKEINTRESOURCE转换资源ID,导致图标加载失败,最终所有项显示默认占位图标。

2. 核心实现要点

  • ImageList创建:指定ILC_COLOR32 | ILC_MASK保证图标透明显示,同时设置与加载图标一致的尺寸(这里用16x16适配小图标模式)。
  • 图标索引管理:ImageList_AddIcon返回的是图标在ImageList中的顺序索引,这才是LVITEM.iImage需要使用的正确值。
  • 列表项属性设置:必须在LVITEM.mask中包含LVIF_IMAGE,否则ListView会忽略图标设置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 00:05:25