我希望CListCtrl始终具有所选项目,例如单选按钮的集合。
我使用了样式:LVS_SHOWSELALWAYS|LVS_SINGLESEL
我一直在为此寻找一种风格,但未能找到它。
答案 0 :(得分:2)
处理WM_LBUTTONDOWN。在CListCtrl派生类中,添加
MyListCtrl.cpp:
BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl)
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
void CMyListCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
UINT uHitFlags;
int nItem = HitTest(point, &uHitFlags);
if (uHitFlags & LVHT_NOWHERE)
{
// eat the message by just returning
return;
}
CListCtrl::OnLButtonDown(nFlags, point);
}
这将阻止鼠标单击进入控件并吃掉该消息。您仍然可以通过编程方式删除选择,但用户将无法点击商品下方空白区域中的任意位置来删除选择。
答案 1 :(得分:1)
我认为没有内置的支持。
从一开始就选择的部分很简单:只需在填充列表后选择一个项目:
// Populate the list
// ...
c_MyList.SetItemState(nItem, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);
另一部分,当用户点击所有项目时,阻止取消选择所有项目,这是非常棘手的。您可以轻松检测列表是否取消选择某个项目,但不能检测该项目是否正在丢失所选状态。即您无法判断是否取消选择另一个或未选中所有项目。原因是控件首先发送“项目X已被取消选择”通知,然后“项目Y已被选中”通知。如果没有选择任何项目,则会获得第一个项目,但不会获得第二个项目。
我想到的一个小想法是捕获NM_CLICK通知并阻止控件取消选择该项目。 所有选择/取消选择通知后,问题是发送 NM_CLICK。
所以,这是我提出的一个小黑客:当一个项目失去所选状态时,存储其项目索引。然后在NM_CLICK通知中,如果激活的项目为-1,则再次选择最后一个未选择的项目:
void CMyDialog::OnLvnItemchangedListaEjesPane(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
if (pNMLV->uChanged & LVIF_STATE)
{
UINT oldSelectionState = (pNMLV->uOldState & LVIS_SELECTED);
UINT newSelectionState = (pNMLV->uNewState & LVIS_SELECTED);
if ( oldSelectionState == LVIS_SELECTED && newSelectionState == 0 )
{ // Deselect item
m_LastDeselectedItem = pNMLV->iItem;
}
// ...
}
*pResult = 0;
}
void CMyDialog::OnNMClickListaEjesPane(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
if (pNMItemActivate->iItem == -1)
{
c_ListaEjes.SetItemState(m_LastDeselectedItem, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);
}
*pResult = 0;
}
它可能无法完全满足您的需求,因为它实际上取消选择该项目然后再次选择它。
可能有更好的解决方案,包括创建自己的CListCtrl子类并拦截点击,检查它们是否会强制进行空选择并阻止它,但你必须确定额外的工作是否值得。
答案 2 :(得分:0)
在设计clistctrl时,只需在对话框编辑器中完成此操作,将属性中的“始终显示选择”和“单选”选项设置为true即可。如果你想通过代码这样做,那么你有正确的方法,但错误的地方。覆盖OnInitDialog并在其中首先调用CDialog :: OnInitDialog,然后设置新样式(使用ModifyStyle)。问题是基类覆盖了样式更改。除此之外,它可能是一些东西,MFC并不以其直观性而着称!
答案 3 :(得分:0)
我解决了这个问题如下:
处理LVN_ITEMCHANGING消息并添加以下行:
lastItem = pNMLV->iItem;
处理NM_CLICK,NM_DBLCLK,NM_RCLICK和NM_RDBLCLK消息,并将这些行添加到所有消息中:
CListCtrl * listCtrl = (CListCtrl *)FromHandle(pNMHDR->hwndFrom);
if (pNMItemActivate->iItem == -1)
listCtrl->SetItemState(m_lastItem, LVIS_SELECTED, LVIS_SELECTED);