如何在 ListControl MFC 中有一个多行项目?

Posted

技术标签:

【中文标题】如何在 ListControl MFC 中有一个多行项目?【英文标题】:How can I have a multi-line item in a ListControl MFC? 【发布时间】:2015-06-10 13:39:49 【问题描述】:

我在 Visual Studio 2013 (C++) 中有一个带有项目列表(报表视图)的 MFC 列表控件

   LVCOLUMN lvColumn;

        lvColumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
        lvColumn.fmt = LVCFMT_LEFT;
        lvColumn.cx = 120;
        lvColumn.pszText = "Full Name";
        ((CListCtrl*)GetDlgItem(IDC_LIST1))->InsertColumn(0, &lvColumn);

        lvColumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
        lvColumn.fmt = LVCFMT_LEFT;
        lvColumn.cx = 75;
        lvColumn.pszText = "Profession";
        ((CListCtrl*)GetDlgItem(IDC_LIST1))->InsertColumn(1, &lvColumn);

        lvColumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
        lvColumn.fmt = LVCFMT_LEFT;
        lvColumn.cx = 80;
        lvColumn.pszText = "Fav Sport";
        ((CListCtrl*)GetDlgItem(IDC_LIST1))->InsertColumn(2, &lvColumn);

        lvColumn.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
        lvColumn.fmt = LVCFMT_LEFT;
        lvColumn.cx = 75;
        lvColumn.pszText = "Hobby";
        ((CListCtrl*)GetDlgItem(IDC_LIST1))->InsertColumn(3, &lvColumn);

        LVITEM lvItem;
        int nItem;

        lvItem.mask = LVIF_TEXT;
        lvItem.iItem = 0;
        lvItem.iSubItem = 0;
        lvItem.pszText = "Sandra C. Anschwitz";
        nItem = ((CListCtrl*)GetDlgItem(IDC_LIST1))->InsertItem(&lvItem);

        ((CListCtrl*)GetDlgItem(IDC_LIST1))->SetItemText(nItem, 1, "Singer");
        ((CListCtrl*)GetDlgItem(IDC_LIST1))->SetItemText(nItem, 2, "HandBall");
        ((CListCtrl*)GetDlgItem(IDC_LIST1))->SetItemText(nItem, 3, "Beach");

如何为全名、职业、运动和爱好设置多行项目?

【问题讨论】:

【参考方案1】:

令人惊讶的是,默认的 CListCtrl 无法做到这一点。但是,通过一些自定义编码(和一些技巧),您可以获得您想要的效果。

首先,您需要从 CListCtrl 派生您自己的类,并为控件样式设置所有者绘制位 (Owner Draw Fixed = true)。在你的父对话框类中,创建一个图像列表(这里是诡计)。图像列表将用于指定列表控件每一行的高度。在下面的示例中,我使用了:

m_imagelist.Create(48, 48, ILC_COLOR4, 10, 10);
m_listctrl.SetImageList(&m_imagelist, LVSIL_SMALL);

您需要使用图像列表的 cxcy 值来满足您的需求。您的控件将使用图像列表来调整每一行的大小,因为它预计会显示图标。接下来,像这样为 DrawItem 添加一个处理程序:

void MyClistCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
    
    CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);

    CString text = _T("Now is the time \nfor all good men\nto come to the aid");
    pDC->DrawText(text , &lpDrawItemStruct->rcItem, DT_TOP);
    // TODO:  Add your code to draw the specified item
    

在我的示例中,这会导致……

这可能不是一个优雅的解决方案,但它确实有效。注意:使用这种方法,每一行都将具有相同的高度。

编辑:有几种方法可以获取行文本。最简单的方法是像这样使用 GetItemText:

CString txt = GetItemText(lpDrawItemStruct->itemID, 0);
pDC->DrawText(txt, &lpDrawItemStruct->rcItem, DT_TOP);

以上假设您使用 CListCtrl 方法之一设置每一行的文本来设置文本。

【讨论】:

非常感谢,您能告诉我如何在 DrawItem() 中嵌入项目文本和其他信息吗?目前,我调用SetItemText(nItem, 1, Actoss.str().c_str()); 现在,如何调用DrawItem()?例如LPDRAWITEMSTRUCT 的值应该是多少? @TOWI_Parallelism DrawItem 在需要渲染所有者绘制控件时调用。你不直接调用它。 MFC 将调用您的实现,让您有机会绘制控件的内容。 LPDRAWITEMSTRUCT 将填写您用于绘制控件的信息。 但是有没有办法在 LPDRAWITEMSTRUCT 中为每个项目嵌入所需的文本?在您的代码中,所有项目都将具有相同的 txt。

以上是关于如何在 ListControl MFC 中有一个多行项目?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 listcontrol mfc 中编辑单元格?

在对话框窗口中使用 ListControl

猎豹MFC--列表控件ListControl

MFC listcontrol导出excel表格

MFC使用ListControl时,第一次左键点击ListControl的列表时无法触发NM_CLICK消息,点击第二次时才能触发

MFC中listcontrol建立的表,怎样判断选中一行并作出响应