Search code examples
cwinapivisual-c++checkboxtreeview

Can't implement treeview with mutually exclusive checkboxes


I need to implement a treeview with following behavior:

When user checks an item, previously checked items get unchecked. I am not native English speaker but I understand this behavior is called mutually exclusive checkboxes.

I have found TVS_EX_EXCLUSIONCHECKBOXES extended style that seemed to suit my needs but I can not use it successfully.

I am setting TVS_CHECKBOXES style properly by using SetWindowLongPtr instead of simply passing it to CreateWindowEx as MSDN recommended. I then use GetWindowLongPtr and SetWindowLongPtr to add the extended style I mentioned above. The code compiles but runs as if I have never added the extended style.

  • I have linked commctrl library and enabled visual styles;
  • I have initialized common controls;

Below is the WM_CREATE handler.

case WM_CREATE:
{
    HWND hwndTV = CreateWindowEx(0, WC_TREEVIEW, L"tv", 
        WS_CHILD | WS_VISIBLE | WS_BORDER | 
        TVS_FULLROWSELECT | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT,
        50, 50, 150, 250, hWnd, (HMENU)4000, hInst, 0);

    // add checkbox

    DWORD dwStyle = GetWindowLongPtr(hwndTV, GWL_STYLE), 
        dwExStyle = GetWindowLongPtr(hwndTV, GWL_EXSTYLE);

    dwStyle |= TVS_CHECKBOXES;
    dwExStyle |= TVS_EX_EXCLUSIONCHECKBOXES;
    
    SetWindowLongPtr(hwndTV, GWL_STYLE, dwStyle);
    SetWindowLongPtr(hwndTV, GWL_EXSTYLE, dwExStyle);

    TVINSERTSTRUCT tvis = { 0 };
    
    tvis.item.mask = TVIF_TEXT;
    tvis.item.pszText = L"ROOT ITEM 1";
    HTREEITEM root1 = TreeView_InsertItem(hwndTV, &tvis);

    tvis.item.mask = TVIF_TEXT;
    tvis.item.pszText = L"ROOT ITEM 2";
    HTREEITEM root2 = TreeView_InsertItem(hwndTV, &tvis);

    tvis.item.mask = TVIF_TEXT;
    tvis.item.pszText = L"First child";
    tvis.hParent = root1;
    tvis.hInsertAfter = TVI_FIRST;
    HTREEITEM child1 = TreeView_InsertItem(hwndTV, &tvis);
}

QUESTIONS:

Have I misunderstood the docs for TVS_EX_EXCLUSIONCHECKBOXES?

  • If not, then how should my code be modified to behave the way I described earlier?
  • If yes, then please tell me so.

Solution

  • TVS_EX_xxx styles aren't "extended window styles", they're "extended treeview styles". They can only be set using the TVM_SETEXTENDEDSTYLE message.

    TreeView_SetExtendedStyle(hwndTV,
               TVS_EX_EXCLUSIONCHECKBOXES, TVS_EX_EXCLUSIONCHECKBOXES);