Tech Support > Microsoft Windows > Development Resources > TreeView Custom Draw - What's Item's Status.
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




Similar Posts