列表视图无法绘制字符串
List View failing to draw strings
我正在尝试使用列表视图将 std::strings
的向量绘制为列表。但是,当我 运行 代码时,没有任何反应。没有错误被抛出:它只是简单的不绘制,我很难过。这是一个最小的可重现示例(我质疑的大部分代码在 case WM_NOTIFY
和 InsertListViewItems
下的 WndProc
中):
//libraries
#pragma comment ("lib", "Comctl32.lib")
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include <windows.h>
// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <vector>
#include <string>
#include <dwrite.h>
#include <d2d1.h>
#include <commctrl.h>
#include <strsafe.h>
#define IDS_APP_TITLE 103
#define IDR_MAINFRAME 128
#define IDD_PRACTICE_DIALOG 102
#define IDD_ABOUTBOX 103
#define IDM_EXIT 105
#define IDI_PRACTICE 107
#define IDI_SMALL 108
#define IDC_PRACTICE 109
#define IDC_MYICON 2
#ifndef IDC_STATIC
#define IDC_STATIC -1
#endif
#define MAX_LOADSTRING 100
#define PROJECT_LIST_VIEW 110
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
std::vector<std::string> stringsVector = { "String1", "String2", "string3" };
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
HWND listViewHandle;
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PRACTICE));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_PRACTICE);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
///////////////////
//Function to insert the items into the list view
//////////////////
BOOL InsertListViewItems(HWND hWndListView, int cItems)
{
LVITEM lvI;
// Initialize LVITEM members that are common to all items.
lvI.pszText = LPSTR_TEXTCALLBACK; //This should send an LVN_GETDISPINFO message
lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;
lvI.stateMask = 0;
lvI.iSubItem = 0;
lvI.state = 0;
// Initialize LVITEM members that are different for each item.
for (int index = 0; index < cItems; index++)
{
lvI.iItem = index;
lvI.iImage = index;
// Insert items into the list.
if (ListView_InsertItem(hWndListView, &lvI) == -1)
return FALSE;
}
return TRUE;
}
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_PRACTICE, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PRACTICE));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
//Create the List View Control
listViewHandle = CreateWindow(WC_LISTVIEW, L"", WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_EDITLABELS, 100, 100, 500, 500, hWnd, (HMENU)PROJECT_LIST_VIEW, hInst, NULL);
InsertListViewItems(listViewHandle, stringsVector.size());
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_NOTIFY:
{
NMLVDISPINFO* plvdi;
OutputDebugStringA("WM_NOTIFY");
switch (((LPNMHDR)lParam)->code)
{
case LVN_GETDISPINFO:
{
////////////////////
//This is the callback that should set the pszText attribute of the items
////////////////////
OutputDebugStringA("LVN_GETDISPINFO\n");
plvdi = (NMLVDISPINFO*)lParam;
const char* inString = stringsVector[plvdi->item.iItem].c_str();
size_t size = strlen(inString) + 1;
wchar_t* outString = new wchar_t[size];
size_t outSize;
mbstowcs_s(&outSize, outString, size, inString, size - 1);
LPWSTR ptr = outString;
StringCchCopy(plvdi->item.pszText, plvdi->item.cchTextMax, outString);
OutputDebugString(outString);
OutputDebugStringA("\n");
delete[] outString;
break;
}
}
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
感谢您的宝贵时间!
正如 Jonathan Potter 和 Remy 所说,您需要至少添加一列才能确保列表正确显示:
LVCOLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
// Initialize LVITEM members that are common to all items.
// Initialize LVITEM members that are different for each item.
lvc.iSubItem = 0;
lvc.pszText = (LPWSTR)L"test";
lvc.cx = 200;
// Insert items into the list.
if (ListView_InsertColumn(hWndListView, 0, &lvc) == -1)
return FALSE;
它对我有用:
我正在尝试使用列表视图将 std::strings
的向量绘制为列表。但是,当我 运行 代码时,没有任何反应。没有错误被抛出:它只是简单的不绘制,我很难过。这是一个最小的可重现示例(我质疑的大部分代码在 case WM_NOTIFY
和 InsertListViewItems
下的 WndProc
中):
//libraries
#pragma comment ("lib", "Comctl32.lib")
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include <windows.h>
// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <vector>
#include <string>
#include <dwrite.h>
#include <d2d1.h>
#include <commctrl.h>
#include <strsafe.h>
#define IDS_APP_TITLE 103
#define IDR_MAINFRAME 128
#define IDD_PRACTICE_DIALOG 102
#define IDD_ABOUTBOX 103
#define IDM_EXIT 105
#define IDI_PRACTICE 107
#define IDI_SMALL 108
#define IDC_PRACTICE 109
#define IDC_MYICON 2
#ifndef IDC_STATIC
#define IDC_STATIC -1
#endif
#define MAX_LOADSTRING 100
#define PROJECT_LIST_VIEW 110
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
std::vector<std::string> stringsVector = { "String1", "String2", "string3" };
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
HWND listViewHandle;
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PRACTICE));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_PRACTICE);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
///////////////////
//Function to insert the items into the list view
//////////////////
BOOL InsertListViewItems(HWND hWndListView, int cItems)
{
LVITEM lvI;
// Initialize LVITEM members that are common to all items.
lvI.pszText = LPSTR_TEXTCALLBACK; //This should send an LVN_GETDISPINFO message
lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE;
lvI.stateMask = 0;
lvI.iSubItem = 0;
lvI.state = 0;
// Initialize LVITEM members that are different for each item.
for (int index = 0; index < cItems; index++)
{
lvI.iItem = index;
lvI.iImage = index;
// Insert items into the list.
if (ListView_InsertItem(hWndListView, &lvI) == -1)
return FALSE;
}
return TRUE;
}
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_PRACTICE, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PRACTICE));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
//Create the List View Control
listViewHandle = CreateWindow(WC_LISTVIEW, L"", WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_EDITLABELS, 100, 100, 500, 500, hWnd, (HMENU)PROJECT_LIST_VIEW, hInst, NULL);
InsertListViewItems(listViewHandle, stringsVector.size());
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_NOTIFY:
{
NMLVDISPINFO* plvdi;
OutputDebugStringA("WM_NOTIFY");
switch (((LPNMHDR)lParam)->code)
{
case LVN_GETDISPINFO:
{
////////////////////
//This is the callback that should set the pszText attribute of the items
////////////////////
OutputDebugStringA("LVN_GETDISPINFO\n");
plvdi = (NMLVDISPINFO*)lParam;
const char* inString = stringsVector[plvdi->item.iItem].c_str();
size_t size = strlen(inString) + 1;
wchar_t* outString = new wchar_t[size];
size_t outSize;
mbstowcs_s(&outSize, outString, size, inString, size - 1);
LPWSTR ptr = outString;
StringCchCopy(plvdi->item.pszText, plvdi->item.cchTextMax, outString);
OutputDebugString(outString);
OutputDebugStringA("\n");
delete[] outString;
break;
}
}
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
感谢您的宝贵时间!
正如 Jonathan Potter 和 Remy 所说,您需要至少添加一列才能确保列表正确显示:
LVCOLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
// Initialize LVITEM members that are common to all items.
// Initialize LVITEM members that are different for each item.
lvc.iSubItem = 0;
lvc.pszText = (LPWSTR)L"test";
lvc.cx = 200;
// Insert items into the list.
if (ListView_InsertColumn(hWndListView, 0, &lvc) == -1)
return FALSE;
它对我有用: