返回

在 Windows GUI 程序中如何将数据从结构体打印到 hListView?

windows

如何在 Windows GUI 程序中将数据从结构体打印到 hListView?

引言

开发 GUI 程序时,我们经常需要在列表视图中显示数据。当数据存储在结构体中时,将其打印到 hListView 可能是一项艰巨的任务。本文将引导你完成在 Windows GUI 程序中从结构体打印数据到 hListView 的步骤,并提供一个示例代码,供你参考。

创建 hListView

首先,你需要创建一个 hListView 窗口。这可以使用 CreateWindowW 函数完成。创建 hListView 后,可以设置其样式并添加列。

hListView = CreateWindowW(WC_LISTVIEW,
    L"",
    WS_CHILD | LVS_REPORT | WS_VISIBLE,
    10, 50, 600, 200, // 适当设置位置和大小
    hWnd,
    (HMENU)IDC_LISTVIEW,
    hInst,
    NULL);

// 设置扩展的列表视图样式,用于完全行选择和网格线。
ListView_SetExtendedListViewStyle(hListView, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);

// 定义列表视图的列。例如,三个用于文件信息列。
LVCOLUMN lvCol = { 0 };
lvCol.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; // 确保文本不会被修改的标志

// 将列添加到 ListView
const int numColumns = 3;
const wchar_t* columnTitles[numColumns] = { L"文件名", L"文件路径", L"播放时间" };
int columnWidths[numColumns] = { 100, 150, 150 };

for (int i = 0; i < numColumns; i++) {
    lvCol.pszText = (LPWSTR)columnTitles[i]; // 安全转换:LVCF_TEXT 标志确保文本不会被修改
    lvCol.cx = columnWidths[i];
    ListView_InsertColumn(hListView, i, &lvCol);
}

添加项目到 hListView

接下来,你需要将数据从结构体添加到 hListView。可以使用 LVITEM 结构来实现。

// 确保索引有效
if (index >= multimediaFiles.size()) {
    OutputDebugString(L"AddMultimediaItemToListView 索引超出范围\n");
    return;
}

const MultimediaFileInfo& fileInfo = multimediaFiles[index];

LVITEM lvItem = { 0 };
lvItem.mask = LVIF_TEXT;
lvItem.iItem = ListView_GetItemCount(hListView); // 获取下一个索引

// 准备文件名缓冲区
WCHAR fileNameBuffer[MAX_PATH];
wcsncpy_s(fileNameBuffer, fileInfo.fileName.c_str(), _TRUNCATE);
lvItem.pszText = fileNameBuffer;
lvItem.iSubItem = 0;  // 设置主项(第 0 列)
int itemIndex = ListView_InsertItem(hListView, &lvItem);

// 确保已插入项目
if (itemIndex == -1) {
    OutputDebugString(L"无法将项目插入 ListView\n");
    return;
}

// 在第 1 列设置文件路径
WCHAR filePathBuffer[MAX_PATH];
wcsncpy_s(filePathBuffer, const_cast<LPWSTR>(multimediaFiles[index].filePath.c_str()), _TRUNCATE);
ListView_SetItemText(hListView, itemIndex, 1, filePathBuffer);

// 在第 2 列设置播放日期和时间
WCHAR dateTimeBuffer[256];
FormatDateTimeString(multimediaFiles[index].playDateTime, dateTimeBuffer, ARRAYSIZE(dateTimeBuffer));
ListView_SetItemText(hListView, itemIndex, 2, dateTimeBuffer);

WCHAR debugMsg[512];
swprintf_s(debugMsg, L"上传的多媒体文件:\n文件名:%s\n文件路径:%s\n播放日期和时间:%s\n",
    fileNameBuffer, filePathBuffer, dateTimeBuffer);
OutputDebugString(debugMsg);

// 附加行以列出 multimediaFiles 中的数据
OutputDebugString(L"列出所有多媒体文件:\n");
for (size_t i = 0; i < multimediaFiles.size(); ++i) {
    swprintf_s(debugMsg, 512, L"索引: %zu,文件名:%s,文件路径:%s,播放日期和时间:%s\n",
        i, multimediaFiles[i].fileName.c_str(), multimediaFiles[i].filePath.c_str(),
        FormatSystemTime(multimediaFiles[i].playDateTime).c_str());  // 假设 FormatSystemTime 是一个用于将 SYSTEMTIME 格式化为字符串的函数
    OutputDebugString(debugMsg);
}

完整代码

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

struct MultimediaFileInfo {
    std::wstring fileName;
    std::wstring filePath;
    SYSTEMTIME playDateTime;  // 预定播放文件的时间
    // 添加其他相关信息
};

std::vector<MultimediaFileInfo> multimediaFiles;

HWND hListView;

void InitializeListView(HWND hWnd)
{
    // 初始化列表视图窗口;创建并设置其样式
    hListView = CreateWindowW(WC_LISTVIEW,
        L"",
        WS_CHILD | LVS_REPORT | WS_VISIBLE,
        10, 50, 600, 200, // 适当设置位置和大小
        hWnd,
        (HMENU)IDC_LISTVIEW,
        hInst,
        NULL);

    // 确保已加载通用控件 DLL,并且已创建列表视图。
    INITCOMMONCONTROLSEX icex;
    icex.dwICC = ICC_LISTVIEW_CLASSES;
    InitCommonControlsEx(&icex);

    // 设置扩展的列表视图样式,用于完全行选择和网格线。
    ListView_SetExtendedListViewStyle(hListView, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);

    // 定义列表视图的列。例如,三个用于文件信息列。
    LVCOLUMN lvCol = { 0 };
    lvCol.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; // 确保文本不会被修改的标志

    // 将列添加到 ListView
    const int numColumns = 3;
    const wchar_t* columnTitles[numColumns] = { L"文件名", L"文件路径", L"播放时间" };
    int columnWidths[numColumns] = { 100, 150, 150 };

    for (int i = 0; i < numColumns; i++) {
        lvCol.pszText = (LPWSTR)columnTitles[i]; // 安全转换:LVCF_TEXT 标志确保文本不会被修改
        lvCol.cx = columnWidths[i];
        ListView_InsertColumn(hListView, i, &lvCol);
    }
}

void LoadMultimediaFile(HWND hListView, HWND hDateTimePicker) {
    // 打开一个对话框,允许用户选择一个文件
    OPENFILENAME ofn;       // 常用对话框结构
    WCHAR szFile[260];      // 文件名缓冲区
    ZeroMemory(&ofn, sizeof(ofn));
    szFile[0] = '\0';

    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = hListView;
    ofn.lpstrFile = szFile;
    ofn.nMaxFile = sizeof(szFile);
    ofn.lpstrFilter = L"多媒体文件\0*.mp4;*.png\0所有文件\0*.*\0";
    ofn.nFilterIndex = 1;
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

    if (GetOpenFileName(&ofn) == TRUE) {
        // 已选择文件,现在从日期时间选择器获取时间
        SYSTEMTIME selectedTime;

        DateTime_GetSystemtime(hDateTimePicker, &selectedTime); // 从控件检索日期和时间

        WCHAR debugTimeStr[256];
        swprintf_s(debugTimeStr, 256, L"选择的日期: %04d-%02d-%02d %02d:%02d:%02d",
            selectedTime.wYear, selectedTime.wMonth, selectedTime.wDay,
            selectedTime.wHour, selectedTime.wMinute, selectedTime.wSecond);
        OutputDebugString(debugTimeStr);

        // 现在将'selectedTime'和选定的文件路径用于加载多媒体文件
        AddMultimediaFile(hListView, szFile, selectedTime);
    }
    // 现在将多媒体项目添加到 ListView
    AddMultimediaItemToListView(hListView, multimediaFiles.size() - 1);