• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1023
  • Last Modified:

ListView items and colour problem.

Hi.

I've been trying to figure this out and I'm about to start banging my head against a wall to see if that helps!

I have a function that determines whether or not a string is in an array (simple boolean result).  If the result is true, I want the corresponding item in a TListView to show in normal text.  If it's not, I want it in bold.

I've had it working fine, until I added subitems - subitems don't appear in my list at all.

Anyway, I've done so many modifications trying to get it to work that I don't have any example code and just require a good example of how to do this.

I also need to change the selected colour for the listview as well.

Thanks in advance,

John.
0
Jaymol
Asked:
Jaymol
  • 4
  • 4
1 Solution
 
geobulCommented:
Hi,

Set OwnerDraw property to true and write something like (OnCustomDrawItem event handler):

procedure TForm1.ListView1CustomDrawItem(Sender: TCustomListView;
  Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
  if cdsSelected in State then begin
    Sender.Canvas.Font.Style := [fsBold];
  end else begin
    if Item.Caption = 'bbb' then begin // your condition here
      Sender.Canvas.Font.Style := [fsBold];
    end else begin
      Sender.Canvas.Font.Style := [];
    end;
  end;
end;

Regards, Geo
0
 
JaymolAuthor Commented:
Thanks Geo, but that doesn't work.

Firstly, it doesn't show the subitems, and secondly, I asked how to change the colour of the selected item as well.

Also, could you explain why you'd set OwnerDraw to true if you're using a CustomDrawItem event (these do not require ownerdraw to be true.)

John.
0
 
JaymolAuthor Commented:
I've got it working - set the OwnerDraw to false and your proc works okay.

Now I just need to change the highlight colour.  How can I do that?

John.
0
Cloud Class® Course: C++ 11 Fundamentals

This course will introduce you to C++ 11 and teach you about syntax fundamentals.

 
geobulCommented:
You are right about OwnerDraw. My mistake. I was misleaded by the help of that property.

You want to change the selected color for the Listview as a whole or different colors for different lines depending on a condition? What is ListView.RowSelect property set to? If it is false, you may try:

  if cdsSelected in State then begin
    Sender.Canvas.Font.Style := [fsBold];
    Sender.Canvas.Font.Color := clRed; // add this line only
  end else begin
    // the same

This way the color of the subitems of the selected item will be to red.

If this doesn't work as you want then we could change the system color settings (Windows color scheme) in OnEnter and restore them back in OnExit  events. Some application events will be involved also. The reason is because I think that ListView uses windows color schemes for selected items.

Regards, Geo
0
 
JaymolAuthor Commented:
Hi Geo.

Thanks for that, but it's the highlight colour that I want to change, not the text colour.  I've had this working by using Sender.Canvas.FillRect, but then the text wasn't visible.  So, I did a Sender.Canvas.TextRect, but then I did not have any subitems visible.

I can do both the things I want to do, just not at the same time!

Thanks,

John.
0
 
geobulCommented:
Hi John,

I knew it could be done. Here it is (OnDrawItem only):

Set OwnerDraw to true again :-)

procedure TForm1.ListView1DrawItem(Sender: TCustomListView;
  Item: TListItem; Rect: TRect; State: TOwnerDrawState);
var
  i: integer;
  X: integer;
begin
  if odSelected in State then begin // selected text
    Sender.Canvas.Font.Color := clRed;
    Sender.Canvas.Brush.Color := clYellow;
  end else begin // regular text - not selected
    Sender.Canvas.Font.Color := clBlack;
    Sender.Canvas.Brush.Color := clWhite;
  end;

  // bold font
  if Item.Caption = 'bbb' then begin // your condition here
    Sender.Canvas.Font.Style := [fsBold];
  end else begin
    Sender.Canvas.Font.Style := [];
  end;

  // draw item and subitems
  Sender.Canvas.FillRect(Rect);
  Sender.Canvas.TextOut(Rect.Left + 1, Rect.Top + 1,Item.Caption);
  if Item.SubItems.Count > 0 then begin
    X := 0;
    for i := 0 to Item.SubItems.Count - 1 do begin
      X := X + (Sender as TListView).Columns.Items[i].Width;
      Sender.Canvas.TextOut(Rect.Left + X, Rect.Top + 1,Item.SubItems[i]);
    end;
  end;
end;

Regards, Geo
0
 
JaymolAuthor Commented:
Spot on Geo!  Thanks a lot for your help.

John.
0
 
geobulCommented:
My pleasure. It was a challenge. Thanks for the grade.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 4
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now