AGB  ·  Datenschutz  ·  Impressum  







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

Abgeleiteter TButton mit Delphi Styles nicht richtig

Ein Thema von Rolf Frei · begonnen am 19. Jun 2022 · letzter Beitrag vom 20. Jun 2022
Antwort Antwort
Rolf Frei

Registriert seit: 19. Jun 2006
629 Beiträge
 
Delphi 11 Alexandria
 
#1

Abgeleiteter TButton mit Delphi Styles nicht richtig

  Alt 19. Jun 2022, 14:12
Ich habe eine von TButton abgeleitete Komponente, die ich mit weiteren Win SDK Featurs ergänzt habe, die von der Delphi Implementation nicht unterstützt werden. Dazu habe ich zwei neue Properties ergänzt und entsprechend die System Flags gesetzt. Das Problem ist nun, dass diese nicht mehr funktionieren, sobald ein Delphi Style aktiviert wurde.

Die neuen Properties sind:

TextAlign: TrfTextAlign
Dieses Property steuert wie der Text im Button platziert wird. Dazu werden die entsprechenden System Styles (BS_xxx) gesetzt. Das Probem ist nun, dass diese beim Einsatz von Delphi Styles nicht richtig ausgewertet werden und der Text immer Links vertikal zentriert angezeigt wird. Das Probelm ist, dass BS_CENTER ($300) auch BS_LEFT ($100) enhält (?) und die Abfrage (TextStyle AND BS_LEFT) = BS_LEFT auch bei BS_CENTER gilt. Daher sollte da zuerst nach BS_CENTER abgefragt werden und erst danach nach BS_LEFT. Auch wird im TButton StyleHook das TextFlag immer auf DT_VCENTER gesetzt und somit die BS_TOP und BS_BOTTOM komplett ignoriert. Das TextFlag sollte doch auch die beiden vertikalen Flags beachten.

WordWrap: Boolean (EDIT: Hat nichts mit den Delphi Styles zu tun sondern betrifft es immer)
Das solle Multiline Funktionalität liefern. Das ist zwar in neueren Delphis nun auch automatisch "ein", aber ich möchte die Multiline Funktion auch gerne ausschalten können. Dieses hat aber leider nun keien Funktinon mehr, weil das intern übersteuert wird.

Delphi-Quellcode:
   TrfTextAlign = (talLeftTop, talLeft, talLeftBottom, talCenterTop, talCenter, talCenterBottom,
               talRightTop, talRight, talRightBottom);

   TrfButton = class(TButton)
   private
      { Private-Deklarationen }
      FMultiLine: Boolean;
      FTextAlign: TrfTextAlign;
      procedure SetMultiLine(Value: Boolean);
      procedure SetTextAlign(Value: TrfTextAlign);
   protected
      { Protected-Deklarationen }
   public
      { Public-Deklarationen }
      constructor Create(AOwner: TComponent); override;
      procedure CreateParams(var Params: TCreateParams); override;
   published
      { Published-Deklarationen }
      property MultiLine: Boolean read FMultiLine write SetMultiLine default True;
      property TextAlign: TrfTextAlign read FTextAlign write SetTextAlign default talCenter;
   end;


implementation

const
   TextAligns: Array[TrfTextAlign] of Cardinal =
               (BS_LEFT or BS_TOP, BS_LEFT, BS_LEFT or BS_BOTTOM,
                BS_CENTER or BS_TOP, BS_CENTER, BS_CENTER or BS_BOTTOM,
                BS_RIGHT or BS_TOP, BS_RIGHT, BS_RIGHT or BS_BOTTOM);

{ TrfButton }

constructor TrfButton.Create(AOwner: TComponent);
begin
   inherited Create(AOwner);
   FMultiLine := True;
   FTextAlign := talCenter;
end;

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

procedure TrfButton.CreateParams(var Params: TCreateParams);
begin
   inherited CreateParams(Params);
   if FMultiLine then
      Params.Style := Params.Style or BS_MULTILINE;
   Params.Style := Params.Style or TextAligns[FTextAlign] or BS_TEXT;
end;

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

procedure TrfButton.SetMultiLine(Value: Boolean);
begin
   if Value <> FMultiLine then begin
      FMultiLine := Value;
      RecreateWnd;
   end;
end;

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

procedure TrfButton.SetTextAlign(Value: TrfTextAlign);
begin
   if Value <> FTextAlign then begin
      FTextAlign := Value;
      RecreateWnd;
   end;
end;
Die Frage ist nun wie ich das lösen kann, damit dieser Code für TextAlign auch bei Nutzung von Delphi Styles funktioniert. Muss ich da wirklich den ButtonStyleHook kopieren und für mich anpassen und wie kriege ich diesen dann in meine Komponente? Oder gibt es da eine einfachere objektbasierende Methode ohne Code zu kopieren?
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.009 Beiträge
 
Delphi 12 Athens
 
#2

AW: Abgeleiteter TButton mit Delphi Styles nicht richtig

  Alt 19. Jun 2022, 14:37
Muss ich da wirklich den ButtonStyleHook kopieren und für mich anpassen und wie kriege ich diesen dann in meine Komponente? Oder gibt es da eine einfachere objektbasierende Methode ohne Code zu kopieren?
Das war aber doch zu erwarten. Der Style übernimmt ja das Zeichnen anstatt der Windows-Standard-Methode. Insofern ist auch zu vermuten, dass er die erweiterten BS_xxx Werte nicht kennt bzw. nicht auswertet.

Im konkreten Fall läuft es darauf hinaus eine neue Klasse von TButtonStyleHook zu deklarieren und dort das DrawButton zu überschreiben. Den Code kannst du erstmal von der originalen Klasse übernehmen und dann am Anfang das LTextFlags entsprechend anzupassen.

Damit der Stylehook auch für deinen TrfButton funktioniert, musst du analog zu TButton einen class constructor und destructor anlegen, in dem der neue Stylehook registriert bzw. de-registriert wird.

Nur so als Idee: Ich würde statt einem TextAlign zwei separate Properties für HAlign und VAlign machen. Das fände ich übersichtlicher als aus neun Möglichkeiten die passende auswählen zu müssen.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Rolf Frei

Registriert seit: 19. Jun 2006
629 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Abgeleiteter TButton mit Delphi Styles nicht richtig

  Alt 19. Jun 2022, 15:16
Ok sowas habe ich befürchtet. Muss ich denn im Create zuerst einen Unregsiter aufrufen, da ja der orignal Hook im Create des Vorfahren bereits gesetzt wurde. Ein weiteres Register mit einer abgeleiteten Klasse, würde doch dann zu einem Fehler führen, wenn ich das richtig sehe. Ist das so richtig oder wie wird das korrekt gemacht?
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.009 Beiträge
 
Delphi 12 Athens
 
#4

AW: Abgeleiteter TButton mit Delphi Styles nicht richtig

  Alt 19. Jun 2022, 16:23
Muss ich denn im Create zuerst einen Unregsiter aufrufen, da ja der orignal Hook im Create des Vorfahren bereits gesetzt wurde.
Nein, es wird immer erst ein Stylehook für die aktuelle Klasse gesucht und falls nicht vorhanden auf einen vererbten zurückgegriffen.

Ein Unregister an dieser Stelle würde eher dazu führen, dass normale Buttons nicht mehr richtig gezeichnet würden.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.009 Beiträge
 
Delphi 12 Athens
 
#5

AW: Abgeleiteter TButton mit Delphi Styles nicht richtig

  Alt 19. Jun 2022, 16:24
Ach ja, das wäre eventuell ein Feature in QP wert. Sowohl die Windows-Implementierung als dann konsequenterweise auch beim Style.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Rolf Frei

Registriert seit: 19. Jun 2006
629 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Abgeleiteter TButton mit Delphi Styles nicht richtig

  Alt 20. Jun 2022, 12:54
Was meinst du genau? Die Implementierung des TextAlign Features in der TButton Basisklasse oder was anderes?

Ich habe es übrigens nun mit Änderung der Flags lösen können. Ich untze BS_CENTER nciht mehr, da das anscheinend der Default ist. Ist mir zwar nachwievor unklar, wieso BS_CENTER auch BS_LEFT enthält und die Auswertung "Style AND x" hier eigentlich falsch ist.

Alte Version, die nicht geht, wegen BS_CENTER
Delphi-Quellcode:
const
   TextAligns: Array[TrfTextAlign] of Cardinal =
               (BS_LEFT or BS_TOP, BS_LEFT, BS_LEFT or BS_BOTTOM,
                BS_CENTER or BS_TOP, BS_CENTER, BS_CENTER or BS_BOTTOM,
                BS_RIGHT or BS_TOP, BS_RIGHT, BS_RIGHT or BS_BOTTOM);
Neue Version, die so zu funktionieren scheint
Delphi-Quellcode:
const
   TextAligns: Array[TrfTextAlign] of Cardinal =
               (BS_LEFT or BS_TOP, BS_LEFT, BS_LEFT or BS_BOTTOM,
                BS_TOP, BS_VCENTER, BS_BOTTOM,
                BS_RIGHT or BS_TOP, BS_RIGHT, BS_RIGHT or BS_BOTTOM);
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.009 Beiträge
 
Delphi 12 Athens
 
#7

AW: Abgeleiteter TButton mit Delphi Styles nicht richtig

  Alt 20. Jun 2022, 13:19
Ist mir zwar nachwievor unklar, wieso BS_CENTER auch BS_LEFT enthält und die Auswertung "Style AND x" hier eigentlich falsch ist.
BS_CENTER ist deklariert als 768, was hex $300 entspricht. Das ist dasselbe wie BS_LEFT or BS_RIGHT .

Das gilt übrigens auch für BS_VCENTER = 3072 = $C00 = BS_TOP or BS_BOTTOM .
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.009 Beiträge
 
Delphi 12 Athens
 
#8

AW: Abgeleiteter TButton mit Delphi Styles nicht richtig

  Alt 20. Jun 2022, 13:32
Was meinst du genau? Die Implementierung des TextAlign Features in der TButton Basisklasse oder was anderes?
Bezieht sich die Frage auf den QP-Eintrag?
In dem Fall würde ich TextAlign und TextVAlign als zusätzliche Features für TCustomButton/TButton vorschlagen.

Bei FMX gibt es das ja schon in TTextSettings. Dort sind es HorzAlign und VertAlign jeweils mit den Werten Center, Leading und Trailing, wobei mich die Benennung hier nicht so ganz überzeugt.

Interessanterweise gibt es das innerhalb der VCL-Styles in StyleAPI.inc auch schon:
Delphi-Quellcode:
  TSeTextAlign = (taTopLeft, taTopCenter, taTopRight, taLeft, taCenter,
    taRight, taBottomLeft, taBottomCenter, taBottomRight);
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Rolf Frei

Registriert seit: 19. Jun 2006
629 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: Abgeleiteter TButton mit Delphi Styles nicht richtig

  Alt 20. Jun 2022, 14:42
BS_CENTER ist deklariert als 768, was hex $300 entspricht. Das ist dasselbe wie BS_LEFT or BS_RIGHT .

Das gilt übrigens auch für BS_VCENTER = 3072 = $C00 = BS_TOP or BS_BOTTOM .
Ja das ist mir schon klar, habe das ja selber schon geschrieben. Die Abfrage in den Styles ist dann aber doch falsch. Da müsste dann unterschieden werden ob es zentriert ist, also auch BS_RIGHT gesetzt ist. Also eine einfache Abfrage mit "Style AND BS_LEFT = BS_LEFT" müsste dann doch "(Style AND BS_LEFT = BS_LEFT) AND (Style AND BS_RIGHT = 0)" sein oder einfacher "Style AND BS_CENTER = BS_LEFT" damit das wirklich richtig ist oder nicht?
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.009 Beiträge
 
Delphi 12 Athens
 
#10

AW: Abgeleiteter TButton mit Delphi Styles nicht richtig

  Alt 20. Jun 2022, 16:49
Die Abfrage in den Styles ist dann aber doch falsch. Da müsste dann unterschieden werden ob es zentriert ist, also auch BS_RIGHT gesetzt ist.
Stimmt - der Code ist nicht korrekt. Fällt halt bisher nicht auf, da es ja aktuell kein TextAlign bei einem Button gibt. Die VCL setzt ja weder BS_LEFT noch BS_RIGHT oder gar BS_CENTER und somit führt der Code im Stylehook immer zu einem LTextFlags := LTextFlags or DT_CENTER .
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  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 08:43 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz