Board index » cppbuilder » TListView drawing OnCustomDrawItem for selected items problem..

TListView drawing OnCustomDrawItem for selected items problem..

Hi,

I'm using BCB4 and trying to change colors of text and background of a
TListView using custom drawing with an "OnCustomDrawItem" handler.
There's no problem changing colors of items that are not selected, but
it seems selected items always get overwritten. This happens regardless
of if the item has the focus or not (my goal is to draw it as if it has
the focus while selected, even if the item does not have the focus).

My code:

void __fastcall TUserSetupForm::DirAccessLstCustomDrawItem(
      TCustomListView *Sender, TListItem *Item, TCustomDrawState State,
      bool &DefaultDraw)
{
  if (Item->Selected) {
    Sender->Canvas->Brush->Color=clHightlight;
    Sender->Canvas->Font->Color=clHightlightText;

  }
  else if (Item->Index>=DirAccessSize) {
    Sender->Canvas->Brush->Color=clInactiveCaption;
    Sender->Canvas->Font->Color=clInactiveCaptionText;
  }
  DefaultDraw=true;

Quote
}

The second part (showing items >= DirAccessSize in a different color)
works fine. The first part gets executed (I can tell from breaking on it
with the de{*word*81}) but the selected item is still rendered in the
default colors when it does not have the focus.

Any ideas?
Thanks!

     Rob Beckers
     Cat Soft

 

Re:TListView drawing OnCustomDrawItem for selected items problem..


Hi Rob,

Quote
> There's no problem changing colors of items that are not selected,
> but it seems selected items always get overwritten.

This is an unfortunate property of the list view common control.
Namely, the selected items are not affected by the changes made in
response to the Custom Draw messages when the CDRF_DODEFAULT flag is
returned (DoDefault set to true).  What you can do, however, is set the
DoDefault parameter to false, then render the items manually in the
color of choice.  Here's an example for vsIcon ViewStyle...

void __fastcall TForm1::ListView1CustomDrawItem(
    TCustomListView *Sender,
    TListItem *Item, TCustomDrawState State, bool &DefaultDraw)
{
    if (State.Contains(cdsSelected))
    {
        ListView1->Canvas->Brush->Color = clRed;  // for example
        ListView1->Canvas->Font->Color = clGreen; // for example

        RECT IconRect = Item->DisplayRect(drIcon);
        RECT CaptionRect = Item->DisplayRect(drLabel);

        // calculate the icon's horizontal position
        int IconLeft = IconRect.left + 0.5 *
                       (IconRect.right - IconRect.left -
                       ListView1->LargeImages->Width);

        // draw the icon
        HIMAGELIST HIml =
            reinterpret_cast<HIMAGELIST>
                (ListView1->LargeImages->Handle);
        ImageList_Draw(HIml, Item->ImageIndex,
                       ListView1->Canvas->Handle,
                       IconLeft, IconRect.top + 2,
                       ILD_TRANSPARENT);

        // draw the caption
        ListView1->Canvas->FillRect(CaptionRect);        
        DrawText(ListView1->Canvas->Handle, Item->Caption.c_str(),
                 Item->Caption.Length(), &CaptionRect,
                 DT_CENTER | DT_WORDBREAK);

        DefaultDraw = false;
        return;
    }
    DefaultDraw = true;    

Quote
}

Other styles can be rendered using a similar technique.

Good luck!

--
Damon Chandler (TeamB)
http://bcbcaq.freeservers.com

Re:TListView drawing OnCustomDrawItem for selected items problem..


Quote
"Damon Chandler (TeamB)" wrote:

> Hi Rob,
> > There's no problem changing colors of items that are not selected,
> > but it seems selected items always get overwritten.

> This is an unfortunate property of the list view common control.
> Namely, the selected items are not affected by the changes made in
> response to the Custom Draw messages when the CDRF_DODEFAULT flag is
> returned (DoDefault set to true).  What you can do, however, is set the
> DoDefault parameter to false, then render the items manually in the
> color of choice.  Here's an example for vsIcon ViewStyle...

Thanks Damon! Your answers are greatly appreciated (not only to my
questions, learned a lot from reading others as well)!

One more thing: This particular ListView is only used in vsReport style,
and has 4 columns. I thought about doing my own drawing but figured that
would involve drawing of all the other items/columns and supporting
things like cutting off items that are too long, show an ellipsis (...)
etc. Not to mention supporting the edit function of the 'caption' item.
In other words, seemed like duplicating much of the underlying control,
and basically ending up with the same as using ownerdraw with all its
complications instead of customdraw. Is my assessment correct? Or is
there an easier way to get this done?

       Rob Beckers
       Cat Soft

Other Threads