AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

FMX.Graphics.TCanvas.FillText drehen

Ein Thema von himitsu · begonnen am 3. Sep 2025 · letzter Beitrag vom 5. Sep 2025
Antwort Antwort
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.719 Beiträge
 
Delphi 12 Athens
 
#1

AW: FMX.Graphics.TCanvas.FillText drehen

  Alt 3. Sep 2025, 14:43
Dann schau ich heute abend daheim nochmal in Ruhe danach.

Hatte vor mehreren Tagen nach sowas gesucht und es dann erstmal aufgegeben/gelassen.
Aber, als ich gestern Abend nochmal an jenem Projekt was geändert hab, war mir das wieder in den Sinn gekommen (hatte angefangen eine DemoForm zu basteln, wo auch Labels drauf sind)
und ich dachte ich frag mal ... vielleicht findet sich ja was für heut Abend (oder Wochenende).
https://www.delphipraxis.net/217731-...ml#post1551367
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von joachimd
joachimd

Registriert seit: 17. Feb 2005
Ort: Weitingen
687 Beiträge
 
Delphi 12 Athens
 
#2

AW: FMX.Graphics.TCanvas.FillText drehen

  Alt 3. Sep 2025, 14:47
müsste vermutlich über

  Canvas.SetMatrix(Canvas.Matrix.CreateRotation(Angle)); zu lösen sein.
Joachim Dürr
Joachim Dürr Softwareengineering
http://www.jd-engineering.de
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.719 Beiträge
 
Delphi 12 Athens
 
#3

AW: FMX.Graphics.TCanvas.FillText drehen

  Alt 3. Sep 2025, 14:53
Ich sag schonmal Danke (falls es dann geht )



es könnte alles so einfach sein

Eine DEMO in der Hilfe, die aus mehr als einer Funktion / paar Codezeilen beseteht
https://docwiki.embarcadero.com/Code...anvas_(Delphi)
und dann kommt niemand auf die Idee sie in den Demos abzulegen
C:\Users\Public\Documents\Embarcadero\Studio\23.0\Samples\
https://github.com/Embarcadero/RADStudio12Demos

oder die sinnloseste "DEMO" der Welt (siehe Screenshot) :
C:\Program Files (x86)\Embarcadero\Studio\23.0\bin\FMXControlStyleViewer.exe
https://embt.atlassian.net/servicede...tal/1/RSS-4015
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
philipp.hofmann

Registriert seit: 21. Mär 2012
Ort: Hannover
950 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: FMX.Graphics.TCanvas.FillText drehen

  Alt 3. Sep 2025, 17:54
Ich nutze bei mir die folgende Funktion, dürfte dem oben kommunizierten entsprechen:

Delphi-Quellcode:
class procedure TDrawUtils.drawRotatedText(Canvas: TCanvas; x,y,xw,angle: Single; color: TAlphaColor; HTextAlign, VTextAlign: TTextAlign; const S: String);
var
  W: Single;
  H: Single;
  R: TRectF;
  SaveMatrix: TMatrix;
  Matrix: TMatrix;
begin
  W := Canvas.TextWidth(S);
  H := Canvas.TextHeight(S);
  r:=RectF(x,y,x+w,y+h);
  if (angle=270) then
    x:=x+((xw-(h*0.25))*0.5);
  case HTextAlign of
    TTextAlign.Center: R.Left := -W / 2;
    TTextAlign.Leading: R.Left := 0;
    TTextAlign.Trailing: R.Left := -W;
  end;
  R.Width := W;
  case VTextAlign of
    TTextAlign.Center: R.Top := -H / 2;
    TTextAlign.Leading: R.Top := 0;
    TTextAlign.Trailing: R.Top := -H;
  end;
  R.Height := H;
  SaveMatrix:=Canvas.matrix;
  matrix:=TMatrix.CreateRotation(DegToRad(angle));
  matrix.m31:=x;
  matrix.m32:=y;
  Canvas.MultiplyMatrix(matrix);
  Canvas.Stroke.Color := color;
  Canvas.Fill.Color := color;
  Canvas.Stroke.Kind := TBrushKind.Solid;
  Canvas.Stroke.Thickness := 1;
  Canvas.FillText(R, S, False, 1, [], HTextAlign, VTextAlign);
  Canvas.SetMatrix(SaveMatrix);
end;
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.719 Beiträge
 
Delphi 12 Athens
 
#5

AW: FMX.Graphics.TCanvas.FillText drehen

  Alt 3. Sep 2025, 22:21
Delphi-Quellcode:
procedure TForm3.FormPaint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF);
var
  Angle: Single;
  Matrix: TMatrix;
begin
  Canvas.Fill.Color := TAlphaColors.Black;
  Angle := -ArcTan2(ClientHeight, ClientWidth);
  Matrix := Canvas.Matrix.CreateRotation(Angle);
  Canvas.SetMatrix(Matrix);
  Canvas.FillText(ClientRect, 'Rotated FMX Text', False, 1, [], TTextAlign.Leading, TTextAlign.Trailing);
Hatte hier als Winkel zuerst 0.3 probiert, aber war nix zu sehn.
Delphi-Quellcode:
  Canvas.Fill.Color := TAlphaColors.Black;
  Canvas.SetMatrix(Canvas.Matrix.CreateRotation(-0.64));
  Canvas.FillText(ClientRect, 'Rotated FMX Text', False, 1, [], TTextAlign.Leading, TTextAlign.Trailing);
Ja, das Erste berechnet auch einen negativen Winkel und der liegt innerhalb des Canvas-Rechtecks.

Wie bei drawRotatedText muß man also noch das X:Y dazurechnen,
bzw. das RectF für FillText ordentlich befüllen.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.719 Beiträge
 
Delphi 12 Athens
 
#6

AW: FMX.Graphics.TCanvas.FillText drehen

  Alt 5. Sep 2025, 01:45
Danke nochmal an Phillip

und der Endkampf mit den Matrizen.


Also die CreateRotation gibt erstmal nur die Richtung vor, von Position 0:0 aus,
dann noch den Nullpunkt der Matrix festlegen
und "von" diesem Nullpunkt aus dann den Text zeichnen.

In diesem Fall die Nullpunkte jeweils in der Mitte (Text mittig im Ziel rotieren)
Delphi-Quellcode:
uses
  System.Math, System.Math.Vectors;

procedure TForm3.FormPaint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF);
begin
  var DrawRect := RectF(100, 200, 200, 250);
  var TextRect := RectF(-DrawRect.Width / 2, -DrawRect.Height / 2,
                        +DrawRect.Width / 2, +DrawRect.Height / 2);
  var DMatrix := TMatrix.CreateRotation(DegToRad(Tag));
  DMatrix.m31 := DrawRect.CenterPoint.X;
  DMatrix.m32 := DrawRect.CenterPoint.Y;
  Tag := Tag + 1;

  Canvas.Stroke.Kind := TBrushKind.Solid;
  Canvas.Stroke.Color := TAlphaColors.Red;
  Canvas.Fill.Color := TAlphaColors.Ghostwhite;
  Canvas.FillRect(DrawRect, 1);

  Canvas.SetMatrix(DMatrix);
  Canvas.Fill.Color := TAlphaColors.Black;
  Canvas.FillText(TextRect, 'Rotated FMX Text', False,
    1, [], TTextAlign.Center, TTextAlign.Center);
end;

procedure TForm3.Timer1Timer(Sender: TObject);
begin
  Self.Invalidate;
end;
Da ich aber eh nur 90°-Winkel brauch, kann ich's vereinfachen und an einer Ecke rotieren
(-90° = links-unten, +90° = rechts-oben und 180° = unten-rechts)
Delphi-Quellcode:
uses
  System.Math, System.Math.Vectors;

procedure TForm3.FormPaint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF);
begin
  var DrawRect := RectF(100, 200, 200, 250);
  var TextRect := RectF(0, 0, DrawRect.Height, DrawRect.Width)
  var DMatrix := TMatrix.CreateRotation(DegToRad(Tag));
  DMatrix.m31 := DrawRect.Left;
  DMatrix.m32 := DrawRect.Bottom;
  Tag := Tag + 1;

  Canvas.Stroke.Kind := TBrushKind.Solid;
  Canvas.Stroke.Color := TAlphaColors.Red;
  Canvas.Fill.Color := TAlphaColors.Ghostwhite;
  Canvas.FillRect(DrawRect, 1);

  Canvas.SetMatrix(DMatrix);
  Canvas.Fill.Color := TAlphaColors.Black;
  Canvas.FillText(TextRect, 'Rotated FMX Text', False,
    1, [], TTextAlign.Leading, TTextAlign.Leading);
end;

procedure TForm3.Timer1Timer(Sender: TObject);
begin
  Self.Invalidate;
end;
Und da ich hier ja eh nur mit 90°-Winkeln arbeite, lassen viele Berechnungen (Sinus und Cosinus) durch Konstanten ersetzen.
Delphi-Quellcode:
uses
  System.Math, System.Math.Vectors;

type
  TMatrixHelper = record helper {(TMatrixConstants)} for TMatrix
    const Identity: TMatrix = (m11: +1; m12: 0; m13: 0; m21: 0; m22: +1; m23: 0; m31: 0; m32: 0; m33: 1);
    const Degree180: TMatrix = (m11: -1; m12: 0; m13: 0; m21: 0; m22: -1; m23: 0; m31: 0; m32: 0; m33: 1);
    const Degree90: TMatrix = (m11: 0; m12: +1; m13: 0; m21: -1; m22: 0; m23: 0; m31: 0; m32: 0; m33: 1);
    const Degree270: TMatrix = (m11: 0; m12: -1; m13: 0; m21: +1; m22: 0; m23: 0; m31: 0; m32: 0; m33: 1);
    constructor Create(m11, m12, m13, m21, m22, m23, m31, m32, m33: Single); overload; // 3D-Matrix
    constructor Create(m11, m12, m21, m22, m31, m32: Single); overload; // 2D-Matrix
    constructor Create90 (m31, m32: Single);
    constructor Create180(m31, m32: Single);
    constructor Create270(m31, m32: Single);
  end;

procedure TForm3.FormPaint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF);
begin
  // unten-links / hochzu von rechts
  var DrawRect := RectF(100, 100, 120, 200);
  var TextRect := RectF(0, 0, DrawRect.Height, DrawRect.Width);
  var DMatrix := TMatrix.CreateRotation(DegToRad(-90));
  DMatrix.m31 := DrawRect.Left;
  DMatrix.m32 := DrawRect.Bottom;
  // besser als Konstante, da die Berechnung nicht genau 0 ergibt (-4.37113882867379e-08)
  //DMatrix := TMatrix.Create(0, -1, +1, 0, DrawRect.Left, DrawRect.Bottom);

  Canvas.Stroke.Kind := TBrushKind.Solid;
  Canvas.Stroke.Color := TAlphaColors.Red;
  Canvas.Fill.Color := TAlphaColors.Ghostwhite;
  Canvas.FillRect(DrawRect, 1);

  Canvas.SetMatrix(DMatrix);
  Canvas.Fill.Color := TAlphaColors.Black;
  Canvas.FillText(TextRect, ' Rotated FMX Text', False, 1, [], TTextAlign.Leading, TTextAlign.Center);
  Canvas.SetMatrix(TMatrix.Identity);

  // oben-rechts / runterzu von links
  DrawRect := RectF(200, 100, 220, 200);
  TextRect := RectF(0, 0, DrawRect.Height, DrawRect.Width); // ergibt natürlich das Gleiche, wie oben
  DMatrix := TMatrix.CreateRotation(DegToRad(+90));
  DMatrix.m31 := DrawRect.Right;
  DMatrix.m32 := DrawRect.Top;
  // besser als Konstante, da die Berechnung nicht genau 0 ergibt (-4.37113882867379e-08)
  //DMatrix := TMatrix.Create(0, +1, -1, 0, DrawRect.Right, DrawRect.Top);

  Canvas.Stroke.Kind := TBrushKind.Solid;
  Canvas.Stroke.Color := TAlphaColors.Red;
  Canvas.Fill.Color := TAlphaColors.Ghostwhite;
  Canvas.FillRect(DrawRect, 1);

  Canvas.SetMatrix(DMatrix);
  Canvas.Fill.Color := TAlphaColors.Black;
  Canvas.FillText(TextRect, ' Rotated FMX Text', False, 1, [], TTextAlign.Leading, TTextAlign.Center);
  Canvas.SetMatrix(TMatrix.Identity);

  // rechts-unten / kopfüber
  DrawRect := RectF(300, 100, 400, 120);
  TextRect := RectF(0, 0, DrawRect.Width, DrawRect.Height);
  DMatrix := TMatrix.CreateRotation(DegToRad(180));
  DMatrix.m31 := DrawRect.Right;
  DMatrix.m32 := DrawRect.Bottom;
  // besser als Konstante, da die Berechnung nicht genau 0 ergibt (-4.37113882867379e-08)
  //DMatrix := TMatrix.Create(-1, 0, 0, +1, DrawRect.Right, DrawRect.Bottom);

  Canvas.Stroke.Kind := TBrushKind.Solid;
  Canvas.Stroke.Color := TAlphaColors.Red;
  Canvas.Fill.Color := TAlphaColors.Ghostwhite;
  Canvas.FillRect(DrawRect, 1);

  Canvas.SetMatrix(DMatrix);
  Canvas.Fill.Color := TAlphaColors.Black;
  Canvas.FillText(TextRect, ' Rotated FMX Text', False, 1, [], TTextAlign.Leading, TTextAlign.Center);
  Canvas.SetMatrix(TMatrix.Identity);
end;

procedure TForm3.Timer1Timer(Sender: TObject);
begin
  Self.Invalidate;
end;
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.719 Beiträge
 
Delphi 12 Athens
 
#7

AW: FMX.Graphics.TCanvas.FillText drehen

  Alt 5. Sep 2025, 05:57
Boar, das war fies.

Das FMX-TGrid nutzt selbst eine Matrix, beim Zeichnen und in den CustomDraw-Events.
Das Canvas der Header und Cells liegt also immer auf Position 0:0,
womit ich deren Matrix in meine Matrix mit einberechnen muß,
sonst wird alles in die erste Zelle übereinander gemalt.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:44 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz