Discussion:
Tree View Control state image list
(too old to reply)
Rob
2007-06-28 02:52:01 UTC
Permalink
I'm trying to implement a tree view in an MFC wizard property sheet that has
check boxes that can be dimmed. In order to do this, I've created an image
list that has the check boxes in each of their 4 possible combinations of
unchecked/checked and enabled/disabled (as well as a blank image at index 0).
However, when I set this image list as the tree view control's state image
list, all I see are blank images where the check boxes should be. (I use the
correct state indices when I add the various items. I'm using commctl32
version 5.80 and Visual Studio 2005, so according to the documentation, I
should be able to have a state image list without a main image list.

The tree control is set with the Check Boxes property set to TRUE. The
bitmap resource that I'm using is a 16-colour bitmap with a white background
that I want to appear as transparent. (I'm using ::LoadImage() and
CImageList::Add() instead of CImageList::Create() in the code, because I want
the greys in the bitmap (in the 'disabled' images) to map to the system 3D
colours.)

Sample code appears below:

class CMyPropPage : public CPropertyPage
{
.
.
.
CTreeCtl mMyTree;
.
.
.
}

BOOL CMyPropPage::OnInitDialog()
{
CImageList ImageList;
HBITMAP hBitmap;
HTREEITEM hParent, hTreeItem;
.
.
.
ImageList.Create(16, 16, ILC_COLOR4, 0, 5);
hBitmap = (HBITMAP)::LoadImage(theApp.hInstance,
MAKEINTRESOURCE(IDB_STATEIMG), IMAGE_BITMAP, 80, 16, LR_LOADMAP3DCOLORS);
ImageList.Add(CBitmap::FromHandle(hBitmap), RGB(255, 255, 255));
mMyTree.SetImageList(&ImageList, GVSIL_STATE);
.
.
.
hTreeItem = mMyTree.InsertItem(TVIF_STATE | TVIF_TEXT, _T("Item 1"), 0,
0, INDEXTOSTATEIMAGEMASK(1), TVIS_STATEIMAGEMASK, 0, TVI_ROOT, TVI_LAST);
hTreeItem = mMyTree.InsertItem(TVIF_STATE | TVIF_TEXT, _T("Item 2"), 0,
0, INDEXTOSTATEIMAGEMASK(2), TVIS_STATEIMAGEMASK, 0, TVI_ROOT, TVI_LAST);
hTreeItem = mMyTree.InsertItem(TVIF_STATE | TVIF_TEXT, _T("Item 3"), 0,
0, INDEXTOSTATEIMAGEMASK(1), TVIS_STATEIMAGEMASK, 0, TVI_ROOT, TVI_LAST);
hParent = hTreeItem;
hTreeItem = mMyTree.InsertItem(TVIF_STATE | TVIF_TEXT, _T("Item 3.1"),
0, 0, INDEXTOSTATEIMAGEMASK(1), TVIS_STATEIMAGEMASK, 0, hParent, TVI_LAST);
.
.
.
}

Can anybody tell me what I'm doing wrong? How do I get the check box images
to appear?
Tom Serface
2007-06-28 13:26:16 UTC
Permalink
I've never tried to do this, but did you really mean ILC_COLOR24 rather than
ILC_COLOR4?

You may also find this article interesting:

http://www.codeproject.com/treectrl/vtree.asp

Tom
Post by Rob
I'm trying to implement a tree view in an MFC wizard property sheet that has
check boxes that can be dimmed. In order to do this, I've created an image
list that has the check boxes in each of their 4 possible combinations of
unchecked/checked and enabled/disabled (as well as a blank image at index 0).
However, when I set this image list as the tree view control's state image
list, all I see are blank images where the check boxes should be. (I use the
correct state indices when I add the various items. I'm using commctl32
version 5.80 and Visual Studio 2005, so according to the documentation, I
should be able to have a state image list without a main image list.
The tree control is set with the Check Boxes property set to TRUE. The
bitmap resource that I'm using is a 16-colour bitmap with a white background
that I want to appear as transparent. (I'm using ::LoadImage() and
CImageList::Add() instead of CImageList::Create() in the code, because I want
the greys in the bitmap (in the 'disabled' images) to map to the system 3D
colours.)
class CMyPropPage : public CPropertyPage
{
.
.
.
CTreeCtl mMyTree;
.
.
.
}
BOOL CMyPropPage::OnInitDialog()
{
CImageList ImageList;
HBITMAP hBitmap;
HTREEITEM hParent, hTreeItem;
.
.
.
ImageList.Create(16, 16, ILC_COLOR4, 0, 5);
hBitmap = (HBITMAP)::LoadImage(theApp.hInstance,
MAKEINTRESOURCE(IDB_STATEIMG), IMAGE_BITMAP, 80, 16, LR_LOADMAP3DCOLORS);
ImageList.Add(CBitmap::FromHandle(hBitmap), RGB(255, 255, 255));
mMyTree.SetImageList(&ImageList, GVSIL_STATE);
.
.
.
hTreeItem = mMyTree.InsertItem(TVIF_STATE | TVIF_TEXT, _T("Item 1"), 0,
0, INDEXTOSTATEIMAGEMASK(1), TVIS_STATEIMAGEMASK, 0, TVI_ROOT, TVI_LAST);
hTreeItem = mMyTree.InsertItem(TVIF_STATE | TVIF_TEXT, _T("Item 2"), 0,
0, INDEXTOSTATEIMAGEMASK(2), TVIS_STATEIMAGEMASK, 0, TVI_ROOT, TVI_LAST);
hTreeItem = mMyTree.InsertItem(TVIF_STATE | TVIF_TEXT, _T("Item 3"), 0,
0, INDEXTOSTATEIMAGEMASK(1), TVIS_STATEIMAGEMASK, 0, TVI_ROOT, TVI_LAST);
hParent = hTreeItem;
hTreeItem = mMyTree.InsertItem(TVIF_STATE | TVIF_TEXT, _T("Item 3.1"),
0, 0, INDEXTOSTATEIMAGEMASK(1), TVIS_STATEIMAGEMASK, 0, hParent, TVI_LAST);
.
.
.
}
Can anybody tell me what I'm doing wrong? How do I get the check box images
to appear?
David Connet
2007-06-28 13:49:46 UTC
Permalink
Something that's bugging me on this is that the OP said they turned on
the checkbox option on the control - and then is managing the checkboxes
themself. I seem to remember that's a problem - ah yes (just looked over
some code) - my control actually ASSERTs that (!(GetStyle() &
TVS_CHECKBOXES)) in the presubclasswindow code.

When you tell Windows that the tree has checkboxes, it tries to manage
the checkmark resource. Which is exactly what you DON'T want since you
have additional states to handle.

Also, do not use the SetCheck api. You'll need to call GetItemState
(handle, TVIS_STATEIMAGEMASK)/SetItemState(handle, INDEXTOSTATEIMAGEMASK
(state_index), TVIS_STATEIMAGEMASK). (And as an added bonus, you can have
items with no checkbox at all by setting image 0. Our tree had a need for
that since there are some items in the tree that cannot be selected, as
opposed to items whose state cannot be changed.)

Dave Connet
Post by Tom Serface
I've never tried to do this, but did you really mean ILC_COLOR24
rather than ILC_COLOR4?
http://www.codeproject.com/treectrl/vtree.asp
Tom
Post by Rob
I'm trying to implement a tree view in an MFC wizard property sheet that has
check boxes that can be dimmed. In order to do this, I've created an
image list that has the check boxes in each of their 4 possible
combinations of unchecked/checked and enabled/disabled (as well as a
blank image at index 0).
However, when I set this image list as the tree view control's state
image list, all I see are blank images where the check boxes should
be. (I use the
correct state indices when I add the various items. I'm using
commctl32 version 5.80 and Visual Studio 2005, so according to the
documentation, I should be able to have a state image list without a
main image list.
The tree control is set with the Check Boxes property set to TRUE.
The bitmap resource that I'm using is a 16-colour bitmap with a white
background
that I want to appear as transparent. (I'm using ::LoadImage() and
CImageList::Add() instead of CImageList::Create() in the code, because I want
the greys in the bitmap (in the 'disabled' images) to map to the
system 3D colours.)
class CMyPropPage : public CPropertyPage
{
.
.
.
CTreeCtl mMyTree;
.
.
.
}
BOOL CMyPropPage::OnInitDialog()
{
CImageList ImageList;
HBITMAP hBitmap;
HTREEITEM hParent, hTreeItem;
.
.
.
ImageList.Create(16, 16, ILC_COLOR4, 0, 5);
hBitmap = (HBITMAP)::LoadImage(theApp.hInstance,
MAKEINTRESOURCE(IDB_STATEIMG), IMAGE_BITMAP, 80, 16,
LR_LOADMAP3DCOLORS);
ImageList.Add(CBitmap::FromHandle(hBitmap), RGB(255, 255, 255));
mMyTree.SetImageList(&ImageList, GVSIL_STATE);
.
.
.
hTreeItem = mMyTree.InsertItem(TVIF_STATE | TVIF_TEXT, _T("Item 1"), 0,
0, INDEXTOSTATEIMAGEMASK(1), TVIS_STATEIMAGEMASK, 0, TVI_ROOT, TVI_LAST);
hTreeItem = mMyTree.InsertItem(TVIF_STATE | TVIF_TEXT, _T("Item 2"), 0,
0, INDEXTOSTATEIMAGEMASK(2), TVIS_STATEIMAGEMASK, 0, TVI_ROOT, TVI_LAST);
hTreeItem = mMyTree.InsertItem(TVIF_STATE | TVIF_TEXT, _T("Item 3"), 0,
0, INDEXTOSTATEIMAGEMASK(1), TVIS_STATEIMAGEMASK, 0, TVI_ROOT, TVI_LAST);
hParent = hTreeItem;
hTreeItem = mMyTree.InsertItem(TVIF_STATE | TVIF_TEXT, _T("Item 3.1"),
0, 0, INDEXTOSTATEIMAGEMASK(1), TVIS_STATEIMAGEMASK, 0, hParent, TVI_LAST);
.
.
.
}
Can anybody tell me what I'm doing wrong? How do I get the check box images
to appear?
Rob
2007-06-28 17:22:08 UTC
Permalink
Post by David Connet
Something that's bugging me on this is that the OP said they turned on
the checkbox option on the control - and then is managing the checkboxes
themself. I seem to remember that's a problem - ah yes (just looked over
some code) - my control actually ASSERTs that (!(GetStyle() &
TVS_CHECKBOXES)) in the presubclasswindow code.
Funny, I didn't get any ASSERTs to that effect. (If your ASSERT is in your
own code, that would explain it.) I tried removing the Check Box style...
Still no check boxes showing up. I don't want any other graphics in the tree
control other than the check box, so I'm not using the main image list. Since
I'm using comctl32.dll v5.80 and the API that came with Visual Studio 2005,
the documentation says I shouldn't have to use a main image list to get my
state graphics to show up.
Post by David Connet
When you tell Windows that the tree has checkboxes, it tries to manage
the checkmark resource. Which is exactly what you DON'T want since you
have additional states to handle.
Also, do not use the SetCheck api. You'll need to call GetItemState
(handle, TVIS_STATEIMAGEMASK)/SetItemState(handle, INDEXTOSTATEIMAGEMASK
(state_index), TVIS_STATEIMAGEMASK). (And as an added bonus, you can have
items with no checkbox at all by setting image 0. Our tree had a need for
that since there are some items in the tree that cannot be selected, as
opposed to items whose state cannot be changed.)
I kind of figured on that one.
David Connet
2007-06-29 14:35:55 UTC
Permalink
Post by Rob
Post by David Connet
Something that's bugging me on this is that the OP said they turned
on the checkbox option on the control - and then is managing the
checkboxes themself. I seem to remember that's a problem - ah yes
(just looked over some code) - my control actually ASSERTs that
(!(GetStyle() & TVS_CHECKBOXES)) in the presubclasswindow code.
Funny, I didn't get any ASSERTs to that effect. (If your ASSERT is in
your own code, that would explain it.)
In my CTreeCtrl derived class, I assert that the CHECKBOX flag has _not_
been turned on since I will cause problems. (I do this both in my
PreSubClassWIndow and OnCreate so the control will work properly either
created directly, or via dialog DDX)

Ah - discovered why I couldn't have the CHECKBOX style - the code needs
to be able to have items that have no checkboxes. When you turn the
checkbox style on, it handles the space key and toggles the checkbox -
this effectively turned an item back on when I didn't want it. I seem to
remember that with the extended "disabled" states, it would do the same.

Since I have turned off the default checkbox extensions, that means I now
have to process mouse and keyboard input to toggle the state. (I made my
tree sent a TVN_SETDISPINFO message specifying the state had changed)
[For the mouse, process LButtonDown and do:
UINT flags;
HTREEITEM hItem = HitTest(point, &flags);
if (hItem && (TVHT_ONITEMSTATEICON & flags) && IsCheckVisible(hItem))
...
(IsCheckVisible is a method that returns whether there is a checkbox
visible - the "..." code contains further tests to determine if the
checkbox is enabled or not)
The same idea applies to KeyDown - there I call GetSelectedItem to get
the HTREEITEM to work with.

[Sorry, I can't post the complete code - that whole company proprietary
thing...]

I can't think of anything else special I did to get it working... (I
wrote the code a couple years ago)

Dave
Rob
2007-06-29 17:20:01 UTC
Permalink
Post by David Connet
I can't think of anything else special I did to get it working... (I
wrote the code a couple years ago)
Just out of curiosity, does your tree control use the main image list as
well as the state image list? Mine does not, as I don't want any images other
than the check boxes, and the documentation says that it's supposed to work
without the main image list for comctl32.dll v5.80 and later (which is what
we're supporting).
David Connet
2007-07-01 14:38:20 UTC
Permalink
Post by Rob
Post by David Connet
I can't think of anything else special I did to get it working... (I
wrote the code a couple years ago)
Just out of curiosity, does your tree control use the main image list
as well as the state image list?
Forgot to mention that last time - Yes and No. The subclass of the tree
contains all the state icon stuff in it. We have a couple of dialogs that
use it as-is, and some others that associate a main image list.

Dave
Rob
2007-06-28 17:14:02 UTC
Permalink
Post by Tom Serface
I've never tried to do this, but did you really mean ILC_COLOR24 rather than
ILC_COLOR4?
No, I did meain ILC_COLOR4. (It's a 16 colour (i.e., 4-bit colour depth)
bitmap.
Post by Tom Serface
http://www.codeproject.com/treectrl/vtree.asp
Thanks. I'll see what I can use from that.
Rob
2007-07-04 02:04:02 UTC
Permalink
I'm trying to use a tree control in one of my dialogues that uses state
images and no main image list. All of the documentation states that, for
comctl32.dll version 5.80 and later, this should be possible, but I'm having
no luck getting the state images to show up. (All I ever get are blank areas
where the images should be.) All examples that I've been given use the main
image list. Has anybody had any success getting a tree control working using
state images only? (And, if so, could you provide me with some code, or
pseudo code if you can't provide real code, that shows me how to get it
done?) I can't, for the life of my, figure out what I'm doing wrong, and I'd
like to get this thing working without hacking around using the main image
list as my state images.
Rob
2007-07-04 23:06:03 UTC
Permalink
I tracked down what was causing all of my state images to be invisible. It
seems that the image list has to stick around as long as the tree control
does. You can't just set the tree view's image list and then let the image
list go out of scope; and that's exactly what I was doing. It would have been
nice if the documentation had been a little more clear on that. :-(

Thanks for all of the help that I got from everyone who posted so far.
Tom Serface
2007-07-05 06:55:46 UTC
Permalink
Oops, we should have suggested that one. I usually make the image list a
member of my class that has the tree control for that very reason. Of
course, that also means you have to make sure you don't created it more than
once as well. Fortunately, it cleans itself up when it goes out of scope.

Tom
Post by Rob
I tracked down what was causing all of my state images to be invisible. It
seems that the image list has to stick around as long as the tree control
does. You can't just set the tree view's image list and then let the image
list go out of scope; and that's exactly what I was doing. It would have been
nice if the documentation had been a little more clear on that. :-(
Thanks for all of the help that I got from everyone who posted so far.
Continue reading on narkive:
Loading...