Tree view check boxes: The extended check box states


Version 6 of the common controls in Windows Vista introduced some new check-box-related extended styles for the tree view controls. Unfortunately, the documentation for them is kind of spare.

TVS_EX_PARTIAL­CHECK­BOXES
Include partial checkbox state if the control has the TVS_CHECK­BOXES style.
TVS_EX_DIMMED­CHECK­BOXES
Include dimmed checkbox state if the control has the TVS_CHECK­BOXES style.
TVS_EX_EXCLUSION­CHECK­BOXES
Include exclusion checkbox state if the control has the TVS_CHECK­BOXES style.

Yeah, that doesn't really explain anything.

Fortunately, more information about what these check box states are for can be found in the documentation for the NSTCSTYLE enumeration.

NSTCS_PARTIAL­CHECK­BOXES
Adds a checkbox icon on the leftmost side of a given item with a square in the center, that indicates that the node is partially selected. Maps to the TVS_EX_PARTIAL­CHECK­BOXES tree view control style.
NSTCS_DIMMED­CHECK­BOXES
Adds a checkbox icon on the leftmost side of a given item that contains an icon of a dimmed check mark, that indicates that a node is selected because its parent is selected. Maps to the TVS_EX_DIMMED­CHECK­BOXES tree view control style.
NSTCS_EXCLUSION­CHECK­BOXES
Adds a checkbox icon on the leftmost side of a given item that contains a red X, which indicates that the item is excluded from the current selection. Without this exclusion icon, selection of a parent item includes selection of its child items. Maps to the TVS_EX_EXCLUSION­CHECK­BOXES tree view control style.

Okay, so that explains what the intended purposes of these new styles are.

Of course, when you use those state images, you can use them to mean whatever you like. Though for consistency with the rest of Windows, you probably want to use them to mean what Windows uses them to mean, just like you should probably use the checked state to mean, y'know, that the thing is selected.

Don't forget that these are tree view extended styles, not window manager extended styles, so you set them by using the TVM_SET­EXTENDED­STYLE message or the corresponding Tree­View_Set­Extended­Style macro.

The documentation for these extended styles says that they must be combined with TVS_CHECK­BOXES, but that is not true; these extended styles imply TVS_CHECK­BOXES; you don't need to set TVS_CHECK­BOXES. In fact, it's worse than that. If you set TVS_CHECK­BOXES first, and then set the extended styles second, you won't get the extended styles at all. That's because of the rules we spelled out last time:

  • Turn on the check boxes, either by setting the TVS_CHECK­BOXES style (if all you want is unchecked and checked) or setting one or more of the TVS_EX_XXX­CHECK­BOXES styles (if you want other states, too).
  • Do not touch any of the checkbox-related styles any more. You get one chance, and that's it.

Okay, so that's really a documentation error, not a quirk.

Anyway, let's take these new extended styles for a spin. Save the scratch program we've been using up until now, because we're going to be reusing functions from it. Grab a new scratch program and make these changes:

#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

BOOL
OnCreate(HWND hwnd, LPCREATESTRUCT lpcs)
{
  // Copy this from the old program.
    g_hwndChild = CreateWindow(WC_TREEVIEW,
    nullptr,
    TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT |
    WS_CHILD | WS_VISIBLE,
    CW_USEDEFAULT, CW_USEDEFAULT,
    CW_USEDEFAULT, CW_USEDEFAULT,
    hwnd, nullptr, g_hinst, 0);

  // New code
  DWORD desiredStyles = TVS_EX_PARTIALCHECKBOXES |
                        TVS_EX_DIMMEDCHECKBOXES  |
                        TVS_EX_EXCLUSIONCHECKBOXES;

  TreeView_SetExtendedStyle(g_hwndChild,
        desiredStyles, desiredStyles);

  // Copy this from the old program
  PopulateTreeView(g_hwndChild);

  return TRUE;
}

void
OnDestroy(HWND hwnd)
{
  // Copy this from the old program
  ImageList_Destroy(TreeView_SetImageList(
    g_hwndChild, nullptr, TVSIL_STATE));
  PostQuitMessage(0);
}

The new image list states are added in the order above: Partial, then dimmed, then exclusion. If you omit one of the states, then the others move up to close the gap. For example, if you ask for partial and exclusion (but not dimmed), then the images are unchecked (1), checked (2), partial (3), and exclusion (4).

Comments (10)

  1. mikeb says:

    > Okay, so that’s really a documentation error, not a quirk

    I’d say it’s both a documentation error *and* a quirk.

  2. dwalker07 says:

    There is LOTS of documentation that’s very much like what’s in the first box above. All over the place, and not just from Microsoft.

    Doc that defines “set frobish=True” by explaining that it sets frobish to True. And not telling you what frobish is.

    All doc that shows how to Set something should also show how to Query that same thing.

    1. cheong00 says:

      I don’t know, sometimes the examples given on the documentation are not that helpful either.

      Either code that show you how to set something in and immediately retrieving back but without explanation on “something”, or just with example on broken link. (Say, the documentation of WTSEnumerateSessions() tell you to find example on KB article, https://support.microsoft.com/en-us/kb/291789 but it’s no longer there. I don’t know KB articles can go away given much of KB in DOS days are still accessible)

      1. florian says:

        I also miss a few KB articles, and not all of them can be recovered from the Internet Archive.

        So I save web pages I’d like to keep as postscript files using the MS Publisher Imagesetter printer driver on FILE:, and then batch-create tiny and compatible PDFs using Ghostscript. That’s also why IE is still my favorite web browser, as it has the most decent printing options.

  3. Brian_EE says:

    It would be cool if you did a series on scroll bars.

    1. Pietro Gagliardi (andlabs) says:

      You mean like the very first series he ever blogged here? =P (Or is there a joke I’m missing?)

      1. pc says:

        Actually, it’d be really great if somebody put together an index of Raymond’s posts. List the series that he’s done, pick some “best-of” and “people new to Raymond should definitely read” posts, and just generally organize some of the decade-and-a-half of content here.

        I find it unlikely that I’d have the time to do so myself, but if somebody’s bored out there, I think it’d be useful and nifty, even though I think I’ve read almost all of the posts at this point.

      2. Brian_EE says:

        I assumed the folks here were smart enough that I didn’t need a /s at the end of my comment.

        1. Tanveer Badar says:

          Life is full of disappointments.

  4. skSdnW says:

    There are some inconsistencies compared to drawing yourself:

    The image type do not match the other checkboxes used in this series.

    You don’t need to handle WM_NOTIFY for the state image to change (mouse and space).

    The return value of TVN_KEYDOWN is ignored, you need to handle NM_TVSTATEIMAGECHANGING to block changes from the keyboard. (Both NM_TVSTATEIMAGECHANGING and TVN_KEYDOWN are documented to ignore this return value)

Skip to main content