Limiting selected checkbox items in a CListCtrl
-
I have a CListCtrl with the LVS_EX_CHECKBOXES style and I want to limit the number of items that the user can select. I have written the following code but (of course) it gets itself in a loop because in changing the state of an item, it causes OnItemchangingLoadingValues() to be called again.
void CSpecimenLoadingDialog::OnItemchangingLoadingValues(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
int nCheckedItems = 0;
for(int i = 0; i < m_loadingVals.GetItemCount(); i++)
{
BOOL bState = ListView_GetCheckState(m_loadingVals.m_hWnd, i);
if(bState)
{
nCheckedItems++;
}
}if(nCheckedItems == 2) { ListView\_SetItemState(m\_loadingVals.m\_hWnd, pNMListView->iItem, FALSE, LVIS\_STATEIMAGEMASK); } \*pResult = 0;
}
What is the correct way to go about doing this? :~
-
I have a CListCtrl with the LVS_EX_CHECKBOXES style and I want to limit the number of items that the user can select. I have written the following code but (of course) it gets itself in a loop because in changing the state of an item, it causes OnItemchangingLoadingValues() to be called again.
void CSpecimenLoadingDialog::OnItemchangingLoadingValues(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
int nCheckedItems = 0;
for(int i = 0; i < m_loadingVals.GetItemCount(); i++)
{
BOOL bState = ListView_GetCheckState(m_loadingVals.m_hWnd, i);
if(bState)
{
nCheckedItems++;
}
}if(nCheckedItems == 2) { ListView\_SetItemState(m\_loadingVals.m\_hWnd, pNMListView->iItem, FALSE, LVIS\_STATEIMAGEMASK); } \*pResult = 0;
}
What is the correct way to go about doing this? :~
softwaremonkey wrote:
because in changing the state of an item, it causes OnItemchangingLoadingValues() to be called again.
But the parameters (i.e., state) passed each time are different. Rather than use a
for()
loop each time an item's state changes, simply check the state passed and use a counter. Then inOnItemchangingLoadingValues()
, you could have something like:void CSpecimenLoadingDialog::OnItemchangingLoadingValues(NMHDR* pNMHDR, LRESULT* pResult)
{
if (nCheckedItems < 2)
{
if (pNMHDR's new state equals checked)
nCheckedItems++;
else
nCheckedItems--;
}
}"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
-
I have a CListCtrl with the LVS_EX_CHECKBOXES style and I want to limit the number of items that the user can select. I have written the following code but (of course) it gets itself in a loop because in changing the state of an item, it causes OnItemchangingLoadingValues() to be called again.
void CSpecimenLoadingDialog::OnItemchangingLoadingValues(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
int nCheckedItems = 0;
for(int i = 0; i < m_loadingVals.GetItemCount(); i++)
{
BOOL bState = ListView_GetCheckState(m_loadingVals.m_hWnd, i);
if(bState)
{
nCheckedItems++;
}
}if(nCheckedItems == 2) { ListView\_SetItemState(m\_loadingVals.m\_hWnd, pNMListView->iItem, FALSE, LVIS\_STATEIMAGEMASK); } \*pResult = 0;
}
What is the correct way to go about doing this? :~
You may add a member variable to your class (or a static variable to the handler function) indicating that the handler is called recursive:
// Header file
private:
m_bIgnoreChgHandling;// Source file
CSpecimenLoadingDialog::CSpecimenLoadingDialog()
{
m_bIgnoreChgHandling = false;
}void CSpecimenLoadingDialog::OnItemchangingLoadingValues(NMHDR* pNMHDR, LRESULT* pResult)
{
// Alternative: Use static variable here
// static bool m_bIgnoreChgHandling = false;
if (!m_bIgnoreChgHandling)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
int nCheckedItems = 0;
// some handling code
if(nCheckedItems == 2)
{
m_bIgnoreChgHandling = true;
ListView_SetItemState(m_loadingVals.m_hWnd, pNMListView->iItem, FALSE, LVIS_STATEIMAGEMASK);
m_bIgnoreChgHandling = false;
}
}
*pResult = 0;
} -
You may add a member variable to your class (or a static variable to the handler function) indicating that the handler is called recursive:
// Header file
private:
m_bIgnoreChgHandling;// Source file
CSpecimenLoadingDialog::CSpecimenLoadingDialog()
{
m_bIgnoreChgHandling = false;
}void CSpecimenLoadingDialog::OnItemchangingLoadingValues(NMHDR* pNMHDR, LRESULT* pResult)
{
// Alternative: Use static variable here
// static bool m_bIgnoreChgHandling = false;
if (!m_bIgnoreChgHandling)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
int nCheckedItems = 0;
// some handling code
if(nCheckedItems == 2)
{
m_bIgnoreChgHandling = true;
ListView_SetItemState(m_loadingVals.m_hWnd, pNMListView->iItem, FALSE, LVIS_STATEIMAGEMASK);
m_bIgnoreChgHandling = false;
}
}
*pResult = 0;
}Clever stuff - thanks :thumbsup: