Mfc 区分CListCtrl中的用户单击和SetChecked()

Mfc 区分CListCtrl中的用户单击和SetChecked(),mfc,click,clistctrl,Mfc,Click,Clistctrl,我有一个带有复选框的CListCtrl,我需要根据一些外部因素启用或禁用它。但是,当列表中有更多项目可以显示时,我不能在控件上使用EnableWindow(FALSE),因为它也会禁用滚动条 因此,我在消息映射中搜索并找到了以下代码: ON_NOTIFY(LVN_ITEMCHANGED, IDC_CHECKBOX_LIST, OnCheckboxChanged) 回调函数的实现方式如下: void CUserPropertiesDialog::OnCheckboxChanged(NMHDR*

我有一个带有复选框的CListCtrl,我需要根据一些外部因素启用或禁用它。但是,当列表中有更多项目可以显示时,我不能在控件上使用EnableWindow(FALSE),因为它也会禁用滚动条

因此,我在消息映射中搜索并找到了以下代码:

ON_NOTIFY(LVN_ITEMCHANGED, IDC_CHECKBOX_LIST, OnCheckboxChanged)
回调函数的实现方式如下:

void CUserPropertiesDialog::OnCheckboxChanged(NMHDR* pNMHDR, LRESULT* pResult)
{
    NM_LISTVIEW* pNMListView = (NM_LISTVIEW*) pNMHDR;
    LVHITTESTINFO hitInfo;

    hitInfo.pt = pNMListView->ptAction;
    int nItem = m_checkBoxList.HitTest(&hitInfo);
    if (hitInfo.flags != LVHT_ONITEMSTATEICON) return;

    std::string groupName = static_cast<LPCTSTR>(m_checkBoxList.GetItemText(nItem, 0));

    if (!CCharmUserAdminGUIApp::getTheCharmUserAdminGUIApp().isAdministrator())
    {
        if (pNMListView->uChanged & LVIF_STATE)
        {
            if (((pNMListView->uNewState & INDEXTOSTATEIMAGEMASK(2)) != 0) && ((pNMListView->uOldState & INDEXTOSTATEIMAGEMASK(1)) != 0))
            {
                CH_INFO1("CUserPropertiesDialog::OnCheckboxChanged - CheckBox Now Selected", groupName);
            }
            else if (((pNMListView->uNewState & INDEXTOSTATEIMAGEMASK(1)) != 0) && ((pNMListView->uOldState & INDEXTOSTATEIMAGEMASK(2)) != 0))
            {
                CH_INFO1("CUserPropertiesDialog::OnCheckboxChanged - CheckBox Now Unselected", groupName);
            }
        }
    }
}
void cuserproperties对话框::OnCheckboxChanged(NMHDR*pNMHDR,LRESULT*pResult)
{
NM_LISTVIEW*pNMListView=(NM_LISTVIEW*)pNMHDR;
LVHITTESTINFO hitInfo;
hitInfo.pt=pNMListView->ptAction;
int nItem=m_checkBoxList.HitTest(&hitInfo);
如果(hitInfo.flags!=LVHT\u ONITEMSTATEICON)返回;
std::string groupName=static_cast(m_checkBoxList.GetItemText(nItem,0));
如果(!CCharmUserAdminGUIApp::getTheCharmUserAdminGUIApp().isAdministrator())
{
如果(pNMListView->uChanged&LVIF_状态)
{
如果(((pNMListView->uNewState&IndexStateAImageMask(2))!=0)和((pNMListView->uOldState&IndexStateAImageMask(1))!=0))
{
Chu INFO1(“cuserproperties对话框::OnCheckboxChanged-复选框已选中”,组名);
}
如果((pNMListView->uNewState&IndexStateAImageMask(1))!=0)和((pNMListView->uOldState&IndexStateAImageMask(2))!=0))则为else
{
CHU INFO1(“cuserproperties对话框::OnCheckboxChanged-复选框现在未选中”,组名);
}
}
}
}
问题是,当用户单击复选框(好!)时调用此函数,但当从代码调用
SetChecked()
函数时也会调用此函数

我曾希望通过检查
hitInfo.flags
可以区分单击和函数,但事实并非如此


除了在函数调用之前/之后设置一些全局标志并在回调中使用它之外,是否还有其他方法来判断是否使用了单击或函数调用?

我在我的程序中使用了相同的标志

但我用的是LVN_。有了这个信息,我可以阻止任何改变

在更改列表框项目的状态之前,我重写了SetCheck(即使它不是虚拟的)并设置了一个标志。内部挂起例程查看设置的标志并允许更改。返回后直接清除该标志

因此,如果使用鼠标执行相同的操作,则不会设置标志,您需要以不同的方式进行检查


我装箱子的时候也是这样。我设置了标志,以便所有更改都可以通过

如果需要基于某些条件启用/禁用,为什么禁用滚动条(以及整个控件)很重要?听起来您正在实现非标准的UI行为。为什么这是非标准的?我想查看列表中的所有复选框条目,但不想切换这些条目。与显示编辑框类似,但禁用编辑功能。为什么要使用
INDEXTOSTATEIMAGEMASK
?您应该使用
LVIS\u statemagemask
Related(问题2):我选择了一个类似的解决方案,在
SetCheck()
之前/之后切换一个标志,这很有效,但感觉有点笨拙。是的。但是,即使是查找最后收到的窗口消息也无济于事。你需要“行动”的背景。一个上下文是“程序操作”,一个上下文是“用户操作”。