I'm writing a simple Win32 program that has a ListView with check box and multi-row selection enabled. :
It seems like checkbox checks and row selections are two distinct behaviors. Is there a way to sync these two behaviors, that whenever a check box is checked that row will be selected and whenever a row selected the corresponding checkbox will be check?
"whenever a row is selected, the corresponding checkbox will be checked"
Check WM_NOTIFY
and LVIS_SELECTED
flag to detect when user selects a row. And use ListView_SetCheckState
to check the check-box:
BOOL CALLBACK DialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static HWND hListView;
switch (msg)
{
case WM_INITDIALOG:
hListView = GetDlgItem(hWnd, IDC_LIST1);
break;
case WM_NOTIFY:
{
NMHDR* header = (NMHDR*)lParam;
NMLISTVIEW* nmlist = (NMLISTVIEW*)lParam;
if (header && header->idFrom == IDC_LIST1 && header->code == LVN_ITEMCHANGED)
if (nmlist->uNewState & LVIS_SELECTED)
ListView_SetCheckState(hListView, nmlist->iItem, 1);
break;
}
...
}
"whenever a check box is checked that row will be selected"
Check WM_NOTIFY
and LVIS_STATEIMAGEMASK
flag to detect when checkbox is checked, then use ListView_SetItemState
to select the row.
Also this can lead to recursive calls, because we change the row in response to checkbox, and we change the checkbox in response to row selection. Use the busy
variable to stop recursive calls.
case WM_NOTIFY:
if (lParam)
{
NMHDR* header = (NMHDR*)lParam;
NMLISTVIEW* nmlist = (NMLISTVIEW*)lParam;
//use `busy` as a flag to prevent recursive calls:
static BOOL busy = FALSE;
if (!busy && header->hwndFrom == hListView && header->code == LVN_ITEMCHANGED)
{
busy = TRUE;
if (nmlist->uNewState & LVIS_SELECTED)
{
//row has been selected => check the checkbox
ListView_SetCheckState(hListView, nmlist->iItem, 1);
}
else if (nmlist->uNewState & LVIS_STATEIMAGEMASK)
{
//checkbox has been changed => select/unselect the row
BOOL checked = ListView_GetCheckState(hListView, nmlist->iItem);
ListView_SetItemState(hListView, nmlist->iItem,
checked ? LVIS_SELECTED : 0, LVIS_SELECTED);
}
busy = FALSE;
}
}
break;