【问题标题】:CListCtrl with checkboxes questions带有复选框问题的 CListCtrl
【发布时间】:2017-05-01 18:57:43
【问题描述】:

列表控件被定义为资源上的单选。

问题 1

我想在我的CListCtrl 的第一列的标题上有一个复选框。在OnInitDialog 我有

    m_list.SetExtendedStyle(m_list.GetExtendedStyle() | LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);

    CString s;
    s.LoadString(IDS_COLUMN1);

    #ifndef HDS_CHECKBOXES
    // Copied from Microsoft SDKs\Windows\v7.0A\Include\CommCtrl.h
    #define HDS_CHECKBOXES  0x0400
    #endif 

    CHeaderCtrl& header = *m_list.GetHeaderCtrl();
    header.ModifyStyle(0, HDS_CHECKBOXES);


    #ifndef HDF_CHECKBOX
    // Copied from Microsoft SDKs\Windows\v7.0A\Include\CommCtrl.h    
    #define HDF_CHECKBOX  0x0040
    #endif 

    LVCOLUMN lc = { 0 };
    lc.mask = LVCF_FMT |LVCF_WIDTH |LVCF_TEXT | LVCF_SUBITEM;
    lc.fmt |= HDF_CHECKBOX;
    lc.cx = 96;
    lc.pszText = (TCHAR*) (LPCTSTR)s;

    m_list.InsertColumn(0, &lc);

如果我添加扩展的|LVS_EX_AUTOCHECKSELECT,它只会显示标题的复选框,这是我绝对不想要的,因为我希望检查动作和选择动作将用于不同的目的。

问题 2

当用户选中或取消选中某个项目时,我需要设置一个布尔值并将其标记为已修改。但我不希望在插入项目时发生此操作,例如在表单加载时填充列表时,但它是在我无意的情况下触发的,因为InsertItem 会在OnItemChanged 上触发“取消选中操作”。

它迫使我用 m_is_inserting 成员标志来调节每个插入:

    m_is_inserting = true;
    m_list.InsertItem(i, m_array[i]->GetName());
    m_is_inserting = false;

并对LVN_ITEMCHANGED 处理程序做出相应反应

void CMyDialog::OnItemChanged(NMHDR* pNMHDR, LRESULT* pResult)
{
    NMLISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;

    if (pNMListView->uChanged & LVIF_STATE)
    {
        if (pNMListView->uNewState & LVIS_SELECTED)
            OnSelect();
        else
        {
            if (pNMListView->iItem != -1)
            {
                if ((pNMListView->uNewState & LVIS_STATEIMAGEMASK) == 0x1000)
                {
                    if (!m_is_inserting)
                    {
                        m_array[pNMListView->iItem]->m_active = false;
                        SetModified();
                    }
                }
                else if ((pNMListView->uNewState & LVIS_STATEIMAGEMASK) == 0x2000)
                {
                    if (!m_is_inserting)
                    {
                        m_array[pNMListView->iItem]->m_active = true;
                        SetModified();
                    }
                }
            }
        }
    }

    *pResult = 0;
}

有没有更好的方法来区分真正的用户选中/取消选中操作和InsertItem 副作用?

问题 3

是否有更好的符号约定来获取选中/取消选中状态?幻数0x10000x2000 毫无意义!

提前致谢。

【问题讨论】:

标签: checkbox mfc side-effects clistctrl


【解决方案1】:

首先插入列标题。然后更改HDF_CHECKBOX。例如:

m_list.SetExtendedStyle(LVS_EX_CHECKBOXES| LVS_EX_FULLROWSELECT);

CHeaderCtrl &header = *m_list.GetHeaderCtrl();
header.ModifyStyle(0, HDS_CHECKBOXES);

m_list.InsertColumn(0, L"Column0", 0, 120, 0);
m_list.InsertColumn(1, L"Column1", 0, 80, 1);
m_list.InsertColumn(2, L"Column2", 0, 80, 2);

HDITEM hdi = { 0 };
hdi.mask = HDI_FORMAT;
header.GetItem(0, &hdi);
hdi.fmt |= HDF_CHECKBOX;
header.SetItem(0, &hdi);

m_list.InsertItem(m_list.GetItemCount(), L"C0", 0);
m_list.InsertItem(m_list.GetItemCount(), L"C1", 0);

m_list.SetCheck(0, 1);
m_list.SetCheck(1, 1);

在处理通知时,您可以使用GetCheck 方法查看项目是否被选中。示例:

if(pNMListView->uChanged & LVIF_STATE)
{
    if(pNMListView->uNewState & LVIS_SELECTED)
    {
        ...
    }
    else if(pNMListView->uNewState & LVIS_STATEIMAGEMASK && pNMListView->iItem >= 0)
    {
        if(m_list.GetCheck(pNMListView->iItem))
            TRACE("%d checked\n", pNMListView->iItem);
    }
}

【讨论】:

  • 谢谢。我的问题的“如何在标题上显示复选框”部分(问题 1)得到了回答。尚未尝试处理通知。旁注:很有可能在CMFCListCtrl/CMFCHeaderCtrlist 的标题上设置一个复选框甚至没有实现,因为我在@987654330 上没有发现HDS_CHECKBOXESHDF_CHECKBOXHDF_CHECKED 的出现@and afxlistctrl.cpp|h 文件!
  • header.SetItem(0, &hdi); 的用途是什么?即使没有这部分代码,第一列也可以是复选框列表。
  • @Zhang 是的,header.SetItem(0, &hdi) 不是必须的。它在标题控件中放置一个复选框,可选。
猜你喜欢
  • 1970-01-01
  • 2020-01-20
  • 1970-01-01
  • 2011-09-11
  • 2011-10-30
  • 1970-01-01
  • 1970-01-01
  • 2014-05-16
  • 1970-01-01
相关资源
最近更新 更多