在SysListView32中创建带图标的列表项时图标不显示求助
SysListView32列表项图标不显示问题排查与解决
问题描述
在Microsoft Visual C/C++ 6.0环境下,给SysListView32控件添加带图标的列表项时,列表项文本正常显示,但图标始终无法加载。尝试过传入NULL、资源索引以及使用GetModuleHandle(NULL),均未解决问题。
相关代码
HWND CreateListView (HWND hwndParent) { INITCOMMONCONTROLSEX icex; // 控件初始化结构 icex.dwICC = ICC_LISTVIEW_CLASSES; InitCommonControlsEx(&icex); RECT rcClient; // 父窗口客户区 GetClientRect (hwndParent, &rcClient); // 创建报表视图的列表控件,允许编辑标签 HWND hWndListView = CreateWindow(WC_LISTVIEW, "", WS_CHILD | LVS_REPORT | LVS_EDITLABELS, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, hwndParent, NULL, (HINSTANCE)GetWindowLong(hwndParent,GWL_HINSTANCE), NULL); return (hWndListView); } VOID SetView(HWND hWndListView, DWORD dwView) { // 获取当前窗口样式 DWORD dwStyle = GetWindowLong(hWndListView, GWL_STYLE); // 仅当视图样式变化时修改窗口样式 if ((dwStyle & LVS_TYPEMASK) != dwView) { SetWindowLong(hWndListView, GWL_STYLE, (dwStyle & ~LVS_TYPEMASK) | dwView); } } BOOL InitListViewColumns(HWND hWndListView, int C_COLUMNS, int FirstColumn) { LPSTR szText[256]; // 临时缓冲区 LVCOLUMN lvc; int iCol; // 初始化LVCOLUMN结构,指定有效字段 lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; // 添加列 for (iCol = 0; iCol < C_COLUMNS; iCol++) { lvc.iSubItem = iCol; lvc.pszText = (LPSTR)szText; lvc.cx = 100; // 列宽(像素) if ( iCol < 2 ) lvc.fmt = LVCFMT_LEFT; // 左对齐 else lvc.fmt = LVCFMT_RIGHT; // 右对齐 // 从字符串资源加载列标题 LoadString((HINSTANCE)GetWindowLong((HWND)GetWindowLong(hWndListView,GWL_HWNDPARENT),GWL_HINSTANCE), FirstColumn + iCol, (LPSTR)szText, sizeof(szText)/sizeof(szText[0])); // 插入列到列表控件 if (ListView_InsertColumn(hWndListView, iCol, &lvc) == -1) return FALSE; } return TRUE; } BOOL InsertListViewItems(HWND hWndListView, LPSTR text, LPVOID iImage) { LVITEM lvI; // 初始化LVITEM公共字段 lvI.pszText = text; // 触发LVN_GETDISPINFO消息 lvI.cchTextMax= strlen(text); lvI.mask = LVIF_TEXT | LVIF_IMAGE |LVIF_STATE; lvI.stateMask = 0; lvI.iSubItem = 0; lvI.state = 0; int index=ListView_GetItemCount(hWndListView)+1; lvI.iItem = index; lvI.iImage = (int)iImage; // 插入列表项 if (ListView_InsertItem(hWndListView, &lvI) == -1) return FALSE; return TRUE; } BOOL InitListViewImageLists(HWND hWndListView, LPVOID IDI_ITEM, HINSTANCE hInstance) { HICON hiconItem; // 列表项图标 HIMAGELIST hLarge; // 大图标视图的图像列表 HIMAGELIST hSmall; // 其他视图的小图标图像列表 // 创建大图标图像列表 hLarge = ImageList_Create(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), ILC_MASK, 1, 1); // 创建小图标图像列表 hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_MASK, 1, 1); // 加载图标并添加到图像列表 hiconItem = LoadIcon(hInstance,(LPCTSTR)IDI_ITEM); ImageList_AddIcon(hLarge, hiconItem); ImageList_AddIcon(hSmall, hiconItem); DestroyIcon(hiconItem); // 给列表控件绑定图像列表 ListView_SetImageList(hWndListView, hLarge, LVSIL_NORMAL); ListView_SetImageList(hWndListView, hSmall, LVSIL_SMALL); return TRUE; } // 调用代码片段 hWnd[1] = CreateListView((HWND)hWnd[0]); InitListViewImageLists((HWND)hWnd[1], NULL, NULL); SetView((HWND)hWnd[1], LVS_ICON); InitListViewColumns((HWND)hWnd[1], 1, IDS_FIRSTCOLUMN); InsertListViewItems((HWND)hWnd[1], "Windows", NULL);
问题根源与修复步骤
1. 图标加载参数无效
当前调用InitListViewImageLists时传入NULL作为图标ID和实例句柄,导致LoadIcon无法加载有效图标。需传入已存在的图标资源ID和正确的实例句柄:
// 假设资源中已定义IDI_MYICON图标 InitListViewImageLists(hWnd[1], (LPVOID)IDI_MYICON, GetModuleHandle(NULL));
2. 列表项图标索引错误
InsertListViewItems中传入NULL作为图标索引,而图标索引是图标在图像列表中的位置(从0开始计数),并非NULL。应传入0(因仅向图像列表添加了一个图标):
InsertListViewItems(hWnd[1], "Windows", (LPVOID)0);
3. 添加错误检查避免空指针
在图像列表创建、图标加载步骤中添加错误检查,提前定位问题:
BOOL InitListViewImageLists(HWND hWndListView, LPVOID IDI_ITEM, HINSTANCE hInstance) { HICON hiconItem; HIMAGELIST hLarge; HIMAGELIST hSmall; hLarge = ImageList_Create(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), ILC_MASK, 1, 1); if (!hLarge) return FALSE; hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_MASK, 1, 1); if (!hSmall) { ImageList_Destroy(hLarge); return FALSE; } hiconItem = LoadIcon(hInstance,(LPCTSTR)IDI_ITEM); if (!hiconItem) { ImageList_Destroy(hLarge); ImageList_Destroy(hSmall); return FALSE; } ImageList_AddIcon(hLarge, hiconItem); ImageList_AddIcon(hSmall, hiconItem); DestroyIcon(hiconItem); ListView_SetImageList(hWndListView, hLarge, LVSIL_NORMAL); ListView_SetImageList(hWndListView, hSmall, LVSIL_SMALL); return TRUE; }
4. 优化控件创建样式
原代码先创建报表视图的ListView再切换到图标视图,可直接在CreateWindow时指定LVS_ICON样式,避免样式切换的潜在问题:
HWND hWndListView = CreateWindow(WC_LISTVIEW, "", WS_CHILD | LVS_ICON | LVS_EDITLABELS, 0, 0, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top, hwndParent, NULL, (HINSTANCE)GetWindowLong(hwndParent,GWL_HINSTANCE), NULL);
修改后可省略SetView调用。
修复后的完整调用示例
hWnd[1] = CreateListView(hWnd[0]); // 初始化图像列表,传入有效图标ID和实例句柄 if (!InitListViewImageLists(hWnd[1], (LPVOID)IDI_MYICON, GetModuleHandle(NULL))) { MessageBox(NULL, "图像列表初始化失败", "错误", MB_ICONERROR); DestroyWindow(hWnd[1]); hWnd[1] = NULL; return; } InitListViewColumns(hWnd[1], 1, IDS_FIRSTCOLUMN); // 传入图标索引0 InsertListViewItems(hWnd[1], "Windows", (LPVOID)0);
内容的提问来源于stack exchange,提问作者winapiadmin
相关产品推荐
相关产品推荐

