列表视图无法绘制字符串

List View failing to draw strings

我正在尝试使用列表视图将 std::strings 的向量绘制为列表。但是,当我 运行 代码时,没有任何反应。没有错误被抛出:它只是简单的不绘制,我很难过。这是一个最小的可重现示例(我质疑的大部分代码在 case WM_NOTIFYInsertListViewItems 下的 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;

它对我有用:

更多参考:How to Add List-View Columns