【问题标题】:MFC CListCtrl - how to move item text to the leftMFC CListCtrl - 如何将项目文本向左移动
【发布时间】:2020-07-17 14:21:02
【问题描述】:

我正在尝试以某种方式实现单列 CListCtrl(或 CMFCListCtrl,没关系),有些行可能有复选框,有些可能没有(我不想同时使用 CListBox ,也不是 CCheckListBox,因为将来我打算使用多个列)。我正在使用LVS_EX_CHECKBOXES 样式,但这会强制每个项目都有一个复选框。然后我使用自定义绘制处理程序手动删除复选框,但是我无法将项目的文本移动到左侧,以便它取代已删除的复选框。

这是我的列表控件的样子:

但我需要它看起来像这样(item2 与左边框对齐,代替已擦除的复选框):

我像这样动态创建列表控件:

    list->Create(WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_REPORT | LVS_NOCOLUMNHEADER
                                            rect, this, SOME_ID);
    list->SetExtendedStyle(list->GetExtendedStyle() | LVS_EX_CHECKBOXES);

我的自定义绘图处理函数如下所示:

我像这样动态创建列表控件:

void MyCListCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
    *pResult = CDRF_DODEFAULT;
    LPNMLVCUSTOMDRAW lpn = (LPNMLVCUSTOMDRAW)pNMHDR;

    if (CDDS_PREPAINT == lpn->nmcd.dwDrawStage)
    {
        *pResult = CDRF_NOTIFYITEMDRAW; // get notification for every row (item)
    }
    else if (CDDS_ITEMPREPAINT == lpn->nmcd.dwDrawStage)
    {
        int row = lpn->nmcd.dwItemSpec;
        if (row == 1) { // we are in the first row (item2)
            lpn->nmcd.rc.left -= 20; // doesn't do anything
            lpn->rcText.left -= 20; // doesn't do anything

            // this erases checkbox from the current row
            SetItemState(row, INDEXTOSTATEIMAGEMASK(0), LVIS_STATEIMAGEMASK);
        }
    }
}

有什么方法可以达到预期的效果吗?我是以正确的方式做的,还是在没有LVS_EX_CHECKBOXES 的情况下使用 CListCtrl 并自己在我想要的地方绘制复选框更好?如果是这样,怎么做?提前致谢。

【问题讨论】:

  • 列表视图不包含复选框。它使用图像来模拟它们。 SetItemState 调用不会“删除 [the] checkbox”,而是应用图像列表中索引 0 处的图像。这是一个完全透明的图像,与复选框图像的大小相同。
  • 感谢指正。此图像列表中是否有任何图像,其大小为“0”,以便文本立即向左移动?或者我可以使用大小为 0 的“复选框”图像和“空”图像创建自己的CImageList,如果可以,我在哪里可以找到这些图像?这行得通吗?我对 MFC 编程很陌生,很抱歉出现这样的问题。
  • A ListView 在使用其标准 复选框/图像功能时不支持您要查找的内容。所以禁用它,然后在需要的地方手动绘制你自己的复选框。这意味着您还必须处理鼠标事件来“切换”您的绘图
  • @RemyLebeau 谢谢。我可以以某种方式使用 CListCtrl 使用的相同图像吗?我的库中无法存储任何资源(如图像等)。
  • 您可以使用DrawFrameControlDrawThemeBackground(如果您想匹配较新的视觉样式)来绘制您的控件位图。

标签: c++ winapi mfc win32gui clistctrl


【解决方案1】:

如果这对你来说是一个选择,你为什么不保持原样呢? 无论如何,第一个版本看起来更加整洁。 第二个版本打破了眼睛的引导。

【讨论】:

  • 这不是答案。请拨打tour
【解决方案2】:

你可以尝试用负值缩进(虽然我没试过):

LV_ITEM lvItem;
lvItem.iItem = nYourItem;
lvItem.iSubItem = 0;
lvItem.mask = LVIF_INDENT;
lvItem.iIndent = -1;

VERIFY(SetItem(&lvItem));

【讨论】:

  • 谢谢,但我已经尝试过了。即使我设置了一些自定义图像列表,它也不起作用(iIndent 乘以图像宽度代表真正的缩进,但它只能通过将文本移动到右侧而不是左侧来起作用)。看起来唯一的选择是手动绘制位图,就像@IInspectable 建议的那样。现在,我只是简单地使用 CListCtrl,带或不带 LVS_EX_CHECKBOXES。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-17
  • 1970-01-01
  • 2019-05-27
  • 1970-01-01
  • 2013-11-22
  • 1970-01-01
相关资源
最近更新 更多