Solved

My own TGraphicControl with Autosize option

Posted on 2004-10-03
7
450 Views
Last Modified: 2008-01-09
hi!
can any experts tell me how to solve the following dillema
I made a new component based on TGraphicControl :

procedure TDarkRotateLabel.paint;
var
  LabelImage   : TBitmap;
  FRenderImage : TBitmap;
  Center       : TPoint;
begin
  inherited;
  if update then
  begin
    LabelImage   := TBitmap.Create;
    FRenderImage := TBitmap.Create;
    with LabelImage do
    try
      if (Self.Transparent) then
      Transparent := true;

      Canvas.Font.Assign(FFont);
      PixelFormat := pf24bit;
      Width  := Canvas.TextWidth(Caption);
      Height := Canvas.TextHeight(Caption);
      Canvas.TextOut(0,0,caption);

      with FRenderImage do
      begin
        if self.Transparent then
        Transparent := true;

        Width  := self.Width;
        height := self.Height;
        PixelFormat := pf24bit;
      end;

      with TJvPaintFX.Create do
      try
        Center.x := (self.Width  div 2);
        Center.y := (self.Height div 2);
        SmoothRotate(LabelImage,FRenderImage, Center.X, Center.Y, FAngle);
      finally
        free;
      end;

      if autosize then
      begin
       { THIS IS WHERE I NEED TO CALCULATE THE AUTOSIZE }    
        self.width := Abs(Trunc(width * cos(fAngle*Pi/180))) + Abs(Trunc(height * sin(fangle*Pi/180)));
        self.height := Abs(Trunc(height * sin(fAngle*Pi/180))) + Abs(Trunc(height * cos(fAngle*Pi/180)));

        self.canvas.Draw(0,0,FRenderImage);
      end else
      self.canvas.Draw(0,0,FRenderImage);
    finally
      FreeAndNil(FRenderImage);
      FreeAndNil(LabelImage);
      free
    end;
  end;
end;

// --------------------------------------------------------

How to make it  act like the TLabel's autosize property?.. ii tought of a "solution" where I can "auto crop"  the excessive whites around the rect of the actual FRendered image.. but I have no idea how to do this....

i searched through various solutions on googlee, but most of them did not exactly what I wanted..



0
Comment
Question by:joepezt
  • 4
  • 3
7 Comments
 
LVL 1

Expert Comment

by:Bart_Thomas
ID: 12216981
It is better when you seperate the two. Painting the rotated bitmap is
different from calculating how big your control must be. Whenever the
Caption or Angle changes you can recalculate how your controls sizes.

And you don't need the TJvPaintFX. Windows has a LOGFONT (TLogFont
in Delphi) which can paint rotated text. It can even anti-alias the text
for you.

Bart Thomas
0
 
LVL 2

Author Comment

by:joepezt
ID: 12217881
hmm yes, I noticed this when setting my control to transparent, i got white "dust" on the edges...

logfont, hmmm
0
 
LVL 1

Accepted Solution

by:
Bart_Thomas earned 50 total points
ID: 12219498
A good place to autosize your control can be the (public) SetBounds function:

procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;

What you can do is create a DoResize procedure who calculates the correct Width and Height.

  DoResize (AWidth,AHeight);
  inherited SetBounds (ALeft,ATop, AWidth,AHeight);

Maybe you know how to calculate the correct Width and Height. If don't, here's some code:

procedure TRotated.DoResize(var AWidth,AHeight: Integer);
var
  sz: TSize;
  x,y: array[0..3] of Double;
  px,py,minx,miny,maxx,maxy: Double;
  p,q,i: Integer;
  logFont: TLogfont;
begin
  GetObject(Canvas.Font.Handle, SizeOf(TLogFont), @logfont);
  logfont.lfQuality := ANTIALIASED_QUALITY;
  logfont.lfEscapement := Trunc (FAngle * 10);
  logfont.lfOrientation := Trunc (FAngle * 10);
  Canvas.Font.Handle := CreateFontIndirect(logfont);

  sz := Canvas.TextExtent(FCaption);
  if (sz.cx = 0) or (sz.cy = 0) then
    Exit;

  x[0] := -sz.cx/2;
  y[0] := -sz.cy/2;

  x[1] := sz.cx/2;
  y[1] := -sz.cy/2;

  x[2] := sz.cx/2;
  y[2] := sz.cy/2;

  x[3] := -sz.cx;
  y[3] := sz.cy/2;

  // x' = x cos (a)  - y sin (a)
  // y' = x sin (a)  + y cos (a)
  for i := 0 to 3 do
    Rotate (x[i],y[i], -FAngle);

  minx := x[0];
  miny := y[0];
  maxx := x[0];
  maxy := y[0];

  for i := 0 to 3 do
  begin
    minx := Min (minx,x[i]);
    miny := Min (miny,y[i]);
    maxx := Max (maxx,x[i]);
    maxy := Max (maxy,y[i]);
  end;

  AWidth := Trunc (maxx - minx);
  AHeight := Trunc (maxy - miny);
  px := AWidth / 2;
  py := AHeight / 2;
  FTextPosition.X := Trunc(x[0]+ px);
  FTextPosition.Y := Trunc(y[0] + py);
end;
0
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

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.

 
LVL 1

Expert Comment

by:Bart_Thomas
ID: 12219567
Ow... I fogot a little detail!
You must use a true type font.
0
 
LVL 2

Author Comment

by:joepezt
ID: 12219927
altho, I did get the original control to work, by creating a new class descendand of TCustomControl
and sending a postmessage WM_USER + 1 with the pointer integer of "self" with invalidate

but I will accept your sollution as well
0
 
LVL 1

Expert Comment

by:Bart_Thomas
ID: 12220438
Allright, thanks.

I noticed you recreate a bitmap with the caption every time you repaint your control. That's can be avoided by adding the LabelImage to the class as private field and repaint it when the caption changes:

  TDarkRotateLabel = class (TCustomControl)
  private
    FCaption: String;
    FLabelImage: TBitmap;

    procedure SetCaption(const Value: String);
  protected
  public
    constructor Create (AOwner: TComponent); override;
    destructor Destroy; override;
    property Caption: String read FCaption write SetCaption;
  end;

{ TDarkRotateLabel }

constructor TDarkRotateLabel.Create(AOwner: TComponent);
begin
  inherited;
  FLabelImage := TBitmap.Create;
end;

destructor TDarkRotateLabel.Destroy;
begin
  FLabelImage.Free;
  inherited;
end;

procedure TDarkRotateLabel.SetCaption(const Value: String);
var
  sz: TSize;
  rect; TRect;
begin
  FCaption := Value;

  FLabelImage.Canvas.Font := Font;
  sz := FLabelImage.Canvas.TextExtent(FCaption);
  FLabelImage.Width := sz.cx;
  FLabelImage.Height := sz.cy;

  SetRect (rect, 0,0,sz.cx,sz.cy);

  FLabelImage.Canvas.Brush.Color := clWhite;
  FLabelImage.Canvas.Brush.Style := bsSolid;
  FLabelImage.Canvas.FillRect(rect);

  SetBkMode (FLabelImage.Canvas.Handle, TRANSPARENT);
  SetTextColor (FLabelImage.Canvas.Handle, clBlack);
  FLabelImage.Canvas.TextOut(0,sz.cy, FCaption);
end;

You even can rotate the text and only blit the image to the target in the Paint-procedure.
0
 
LVL 2

Author Comment

by:joepezt
ID: 12220676
ah, thanks!, I will see if i can use some of this. the setbkmode might be usefull...
I do save my lavelimage to a temporary image declared in privatesection, and if set update := true when I need to invalidate to be sure I can reupdate my image. if update = false then just repaint the old image..
0

Featured Post

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

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.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…
I've attached the XLSM Excel spreadsheet I used in the video and also text files containing the macros used below. https://filedb.experts-exchange.com/incoming/2017/03_w12/1151775/Permutations.txt https://filedb.experts-exchange.com/incoming/201…

839 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question