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
655 Beiträge
 
Delphi 11 Alexandria
 
#1

Abgeleiteter TButton mit Delphi Styles nicht richtig

  Alt 19. Jun 2022, 15: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.609 Beiträge
 
Delphi 12 Athens
 
#2

AW: Abgeleiteter TButton mit Delphi Styles nicht richtig

  Alt 19. Jun 2022, 15: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
655 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Abgeleiteter TButton mit Delphi Styles nicht richtig

  Alt 19. Jun 2022, 16: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.609 Beiträge
 
Delphi 12 Athens
 
#4

AW: Abgeleiteter TButton mit Delphi Styles nicht richtig

  Alt 19. Jun 2022, 17: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.609 Beiträge
 
Delphi 12 Athens
 
#5

AW: Abgeleiteter TButton mit Delphi Styles nicht richtig

  Alt 19. Jun 2022, 17: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
655 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Abgeleiteter TButton mit Delphi Styles nicht richtig

  Alt 20. Jun 2022, 13: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
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 01:39 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 by Thomas Breitkreuz