- TreeView Custom Draw - What's Item's Status.
- Posted by Larry Lindstrom on May 8th, 2007
Hi Folks:
Developing on XP Media, VC6, WIN32, no MFC.
I've done a lot of work with Owner Draw List Boxes and Combo Boxes,
but I'm doing a TreeView and I'm unfamiliar with Custom Draw.
I've set the TreeView to draw white text on a blue background.
When drawing an item that is selected, I'd like to reverse those
colors, blue text on white.
I've made a little progress, after using SetWindowLongPtr() to
return CDRF_NOTIFYITEMDRAW. That was advice from the archives, and
MSDN offered no hint that it wasn't just a simple return value from
WM_NOTIFY.
So now I'm receiving a CDDS_ITEMPREPAINT. I want to get the
state of the treeview item from NMCUSTOMDRAW's uItemState. I've
isolated one of the treeview items, whose parameter is an enumeration
MENU_ITEM_EVENTS, and selected it. But like all of the items, it's
uItemState is zero.
I expect there a flaws in my logic for actually setting the colors
of a selected item, and I'd appreciate any advice. But right now I'm
wondering how I determine if a treeview item is selected during a
custom draw.
Here is my code. I'm inserting some clauses that will set test_val,
so I can use breakpoints to figure this out.
DWORD process_main_menu_tree_custom_draw(HWND hdlg,
PROCESS_RECORD *process_record_ptr,
NMTVCUSTOMDRAW *tv_custom_draw_nmhdr_ptr)
{
DWORD return_val = 0;
NMCUSTOMDRAW *custom_draw_nmhdr_ptr = NULL;
#ifdef _DEBUG
int test_val = 0;
#endif
if(tv_custom_draw_nmhdr_ptr != NULL)
{
custom_draw_nmhdr_ptr = &tv_custom_draw_nmhdr_ptr->nmcd;
switch(custom_draw_nmhdr_ptr->dwDrawStage)
{
case CDDS_PREPAINT:
return_val = CDRF_NOTIFYITEMDRAW;
// return_val = CDRF_NOTIFYSUBITEMREDRAW;
break;
case CDDS_ITEMPREPAINT:
#ifdef _DEBUG
if(custom_draw_nmhdr_ptr->lItemlParam ==
MENU_ITEM_EVENTS)
{
test_val = 2;
}
#endif
#ifdef _DEBUG
if(custom_draw_nmhdr_ptr->uItemState ==
CDIS_SELECTED)
{
test_val = 1;
}
#endif
if(custom_draw_nmhdr_ptr->uItemState == CDIS_FOCUS)
{
// The item is selected. Inverse the text
// and background colors.
SetTextColor(custom_draw_nmhdr_ptr->hdc,
BLUE_COLOR);
SetBkColor(custom_draw_nmhdr_ptr->hdc,
WHITE_COLOR);
return_val = CDRF_DODEFAULT;
#if 0
tv_custom_draw_nmhdr_ptr->clrText = BLUE_COLOR;
tv_custom_draw_nmhdr_ptr->clrTextBk =
WHITE_COLOR;
return_val = CDRF_NEWFONT;
#endif
}
else
{
return_val = CDRF_DODEFAULT;
}
break;
}
}
return return_val;
}
I appreciate any advice.
Thanks
Larry
- Posted by Christian ASTOR on May 8th, 2007
Larry Lindstrom wrote:
LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)lParam;
LPNMTVCUSTOMDRAW pnmcd =(LPNMTVCUSTOMDRAW)lParam;
switch(pnmtv->hdr.code)
{
case NM_CUSTOMDRAW:
switch (pnmcd->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
return CDRF_NOTIFYITEMDRAW;
case CDDS_ITEMPREPAINT:
if (pnmcd->nmcd.uItemState == (CDIS_FOCUS | CDIS_SELECTED))
{
pnmcd->clrText = RGB(255, 255, 0);
pnmcd->clrTextBk = RGB(255, 0, 0);
}
//.....etc
- Posted by Larry Lindstrom on May 9th, 2007
Christian ASTOR wrote:
Thanks Christian:
I've made one change to my function. the default return value
is now CDRF_DODEFAULT, so unless I choose to set a value, that is
returned.
Now I'm wondering how these states get set.
I can single click on an item of the TreeView, and the item's
CDDS_ITEMPREPAINT has the uItemState of 0.
Do I have to set the value in uItemState?
I'm having trouble underatanding what's happening.
Here are the items in the treeview:
Organization
Contacts
All
Persons
Organizations
Events
Exit
The application starts with all contacts being displayed. So I
send SendMessage(..., TVM_SELECTITEM, TVGN_CARET, ...) with the "ALL"
handle to the treeview.
The treeview's custom draw code then receives a series of
CDDS_ITEMPREPAINT messages, and each message has uItemState
of 0. So nothing special happens to the selected item's
text.
If "Events" is clicked, a TVM_SELECTITEM is sent to the
listbox, with the treeitem handle of the Events item, and a modal
dialog is popped up.
Custom draw is again called, and again, each CDDS_ITEMPREPAINT
has a uItemState of 0.
This is when things start to work. After the modal dialog
that is displayed as the result of the "Events" is closed,
TVM_SELECTITEM to select "All Contacts" is sent to the treeview.
And now uItemState for "All" is 0x11, and "All" is hilighted
properly.
Clicking on "Events" causes TVM_SELECTITEM to be sent to
the listview, but again, all of the items referenced in the
CDDS_ITEMPREPAINT messages shows uItemState as 0.
So how does an item get selected, so the CDIS_FOCUS and
CDIS_SELECTED flags are asserted?
Thanks
Larry