Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1412
  • Last Modified:

TListView - OnAdvancedCustomDrawItem Shadowed Text

I have a TListView working like the Windows desktop. Basically icons with text underneath. The end user is also able to set their own background.

Now, like the Windows desktop I want to add a shadow to the icons caption. This is because if part of the background is white or a light color, the text will be very hard to see.

So, I wanted to use the AdvancedCustomDrawItem with the Stage being cdPostPaint. This way the item is already painted and I could do just the shadowing.

Now, I need the area which the caption is drawn. So I thought to use:

IconCaptionArea := Item.DisplayRect(drLabel);

Open in new window


But, this doesn't return anything but null values. I stepped through the code and ListView_GetItemRect() returns True but the rect is full of zero's.

Any ideas? I'd also accept workarounds as well.
0
ThievingSix
Asked:
ThievingSix
  • 2
1 Solution
 
Ephraim WangoyaCommented:
I tried the DisplayRect and it returned the correct TRect, both in Delphi7 and Delphi2010

procedure TForm1.ListView1AdvancedCustomDrawItem(Sender: TCustomListView;
  Item: TListItem; State: TCustomDrawState; Stage: TCustomDrawStage;
  var DefaultDraw: Boolean);
var
  R: TRect;
  PrevCanvas: Graphics.TCanvas;

  procedure DrawSample3D(const ACanvas : TCanvas; const ACaption: string;
    const X, Y: Integer; const AColor : TColor);
  begin
    ACanvas.Brush.Style := bsClear;
    ACanvas.Pen.Mode := pmCopy;
    ACanvas.Pen.Style := psSolid;
    //Dark Shadow
    ACanvas.Font.Color := clGray;
    ACanvas.TextOut(X + 1, Y + 1, ACaption);
    //Light Shadow
    ACanvas.Font.Color := clWhite;
    ACanvas.TextOut(X - 1, Y - 1, ACaption);
    //Text
    ACanvas.Font.Color := AColor;
    ACanvas.TextOut(X, Y, ACaption);
  end;

begin
  R := Item.DisplayRect(drLabel);
  DrawSample3D(Sender.Canvas, Item.Caption, R.Left + 2, R.Top, clBlack);
end;
0
 
ThievingSixAuthor Commented:
How weird, it seems that when stepping through the first few iterations it returns a blank rect. But it eventually fills on a later call to CustomDraw().

Below is what I'm using now. Too bad it doesn't work with long single words. Turns out like:
procedure TfrmDesktop.lvDesktopManagerCustomDrawItem(Sender: TCustomListView;
  Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
var
  IconCaptionArea : TRect;
  IconCaption : String;
  OStyle : TBrushStyle;
  OColor : TColor;
  DrawFlags : DWORD;
begin
  IconCaptionArea := Item.DisplayRect(drLabel);
  With IconCaptionArea Do
    begin
    Left := Left + 3;
    Top := Top + 1;
  end;
  With Sender.Canvas Do
    begin
    OStyle := Brush.Style;
    OColor := Font.Color;
    Try
      Brush.Style := bsClear;
      Font.Color := InverseColor(OColor);
      FillRect(IconCaptionArea);
      IconCaption := Item.Caption;
      UniqueString(IconCaption);
      FillRect(IconCaptionArea);
      DrawFlags := DT_TOP Or DT_NOPREFIX Or DT_EDITCONTROL Or DT_CENTER Or
                   DT_WORDBREAK Or DT_WORD_ELLIPSIS Or DT_END_ELLIPSIS Or
                   DT_INTERNAL;
      DrawText(Handle, IconCaption, -1, IconCaptionArea, DrawFlags);
    Finally
      Brush.Style := OStyle;
      Font.Color := OColor;
    end;
  end;
end;

Open in new window

Untitled.png
0
 
ThievingSixAuthor Commented:
Can't believe I believed it didn't work.
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

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