RadioButton mit WordWrap

Rund um die LCL und andere Komponenten
Antworten
LazProgger
Beiträge: 63
Registriert: Di 11. Mär 2014, 00:33

RadioButton mit WordWrap

Beitrag von LazProgger »

Den Zeilenumbruch konnte ich schon mit der folgenden Funktion realisieren:

Code: Alles auswählen

 
  procedure RadioButtonEnableWordWrap(ARadioButton: TRadioButton);
    var
      rb: DWORD;
    begin
 
      rb := GetWindowLong(ARadioButton.Handle, GWL_STYLE);
 
      if rb <> 0 then begin
         rb := rb or BS_MULTILINE or BS_VCENTER;
         SetWindowLong(ARadioButton.Handle, GWL_STYLE, rb);
         ARadioButton.Invalidate;
      end;
 
    end;
 
Das Problem ist nun, dass die AutoSize-Berechnung da offenbar nicht mitspielt. Das heißt: Der Text bricht zwar um, aber wird oben und unten abgeschnitten. Zur Verdeutlichung habe ich mal einen Screenshot und ein kleines Beispielprojekt angehängt.
Screenshot
Screenshot
multilinerb.png (12.99 KiB) 1574 mal betrachtet
Kann mir jemand sagen, was da noch fehlt, damit es funktioniert? Oder wie ich das ansonsten realisieren kann? Der RadioButton hat ja leider von sich aus noch keine WordWrap-Eigenschaft...
Dateianhänge
MultiLineRadioButton.zip
Beispielprojekt
(2.82 KiB) 79-mal heruntergeladen

LazProgger
Beiträge: 63
Registriert: Di 11. Mär 2014, 00:33

Re: RadioButton mit WordWrap

Beitrag von LazProgger »

So, jetzt auch mit Anhängen, das Forum funktioniert wieder...

Benutzeravatar
theo
Beiträge: 10856
Registriert: Mo 11. Sep 2006, 19:01

Re: RadioButton mit WordWrap

Beitrag von theo »

LazProgger hat geschrieben:Oder wie ich das ansonsten realisieren kann?
Kürzeren Text schreiben und den langen Text in einen Hint packen, wie es die IDE auch macht?
Dateianhänge
cbhint.png

LazProgger
Beiträge: 63
Registriert: Di 11. Mär 2014, 00:33

Re: RadioButton mit WordWrap

Beitrag von LazProgger »

Ist leider keine Lösung.. Mit anderer Lösung meinte ich eher so etwas wie OwnerDraw (falls das geht) oder vergleichbares um den Umbruch hinzubekommen.

wp_xyz
Beiträge: 5129
Registriert: Fr 8. Apr 2011, 09:01

Re: RadioButton mit WordWrap

Beitrag von wp_xyz »

Wahrscheinlich musst du dir deinen eigenen Nachfahren von TCheckbox bauen, denn an die Größenberechnung kommst du m.E. von außen nicht ran. Außerdem geht deine Lösung nur für Windows.

Oder - falls dir der automatische Zeilenumbruch weniger wichtig ist als die Möglichkeit, die Checkbox mehrzeilig zu gestalten - nimm TCheckboxThemed von der LazControls-Palette, da wurde gerade heute die Mehrzeiligkeit gefixt. Du musst allerdings den Text zur Laufzeit mit manuellen Umbrüchen eingeben.

Warf
Beiträge: 2118
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: RadioButton mit WordWrap

Beitrag von Warf »

Du könntest einen eigenen Nachfahren der Klasse tcustomcheckbox schreiben und im setter der Capitol über Font oder Cancas die Größe selbst errechnen

Und wenn du das Windows spezifische weg haben willst kannst du glaube ich den Text sogar selbst Zeichnen lassen

LazProgger
Beiträge: 63
Registriert: Di 11. Mär 2014, 00:33

Re: RadioButton mit WordWrap

Beitrag von LazProgger »

Es geht mir um den automatischen Zeilenumbruch. Da ich nicht weiß wie groß das Fenster, die Schrift etc sein wird, kann ich leider vorher nicht wissen, wo die richtige Stelle für einen Zeilenumbruch wäre und ihn vorher setzen, zumal es ja auch schön wäre, wenn sich die Größe automatisch anpasst, wenn man die Fenstergröße ändert, wie es ja auch beim Label schon funktioniert.

Plattformunabhängig wäre natürlich super, dann müsste man den Text allerdings vermutlich selber zeichnen. Ich habe mal versucht einen eigenen Nachfahr zu schreiben, komme aber an dieser Stelle nicht mehr weiter:

Code: Alles auswählen

 
 
unit RadioButtonWordWrap;
 
{$mode objfpc}{$H+}
 
interface
 
uses
  Classes, StdCtrls, SysUtils, Windows, Graphics, Math;   
 
type
 
  { TRadioButtonWordWrap }
 
  TRadioButtonWordWrap = class(TRadioButton)
  private
    FWordWrap: boolean;
    procedure SetWordWrap(AValue: boolean);
  protected
    procedure CalculatePreferredSize(var PreferredWidth, PreferredHeight: Integer; WithThemeSpace: Boolean); override;
    //procedure Paint; override;     <-- gibt es nicht
  public
    constructor Create(AOwner: TComponent); override;
  published
    property WordWrap: boolean read FWordWrap write SetWordWrap;
  end;
 
 
implementation
 
 
{ TRadioButtonWordWrap }
 
constructor TRadioButtonWordWrap.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  self.FWordWrap := false;
end;
 
procedure TRadioButtonWordWrap.SetWordWrap(AValue: boolean);
var
  rb: DWORD;
begin
  if FWordWrap = AValue then Exit;
 
  FWordWrap := AValue;
 
  rb := GetWindowLong(self.Handle, GWL_STYLE);
 
  if rb <> 0 then begin
 
     if AValue then begin
        rb := rb or BS_MULTILINE or BS_VCENTER;
     end else begin
        rb := rb and not BS_MULTILINE and not BS_VCENTER;
     end;
 
     SetWindowLong(self.Handle, GWL_STYLE, rb);
     self.Invalidate;
  end;
 
end;
 
procedure TRadioButtonWordWrap.CalculatePreferredSize(var PreferredWidth, PreferredHeight: Integer; WithThemeSpace: Boolean);
var
  bmp: TBitmap;
  ALines: integer;
begin
  inherited CalculatePreferredSize(PreferredWidth, PreferredHeight, WithThemeSpace);
 
  if self.FWordWrap then begin
     bmp := TBitmap.Create;
     bmp.Canvas.Font.Assign(self.Font);
     ALines := ceil(bmp.Canvas.TextWidth(self.Caption) / (self.Width - 25));  
     PreferredHeight := ALines * bmp.Canvas.TextHeight(self.Caption);
     bmp.Free;
  end;
 
end;   
 
//procedure TRadioButtonWordWrap.Paint;
//begin
  // self.canvas gibt es leider nicht...
//end;
 
 
end.    
 
 
Leider gibt es keine Paint-Prozedur die ich einfach überschreiben könnte, wie es bei anderen Controls ja geht... Auch einen Canvas gibt es beim RadioButton nicht worauf ich zeichnen könnte. Wie kann man dann den Text selber zeichnen?

Bei der Berechnung der nötigen Höhe komme ich auch nicht wirklich weiter, man könnte hier zwar mit TextWidth arbeiten (siehe mein Code), aber ich weiß ja zum Beispiel nicht wie viel Platz durch das Feld für den Haken drauf geht und wo genau ein Wort umbricht, daher sind die Werte ungenau, gerade in Grenzfällen (sieht man wenn man das Fenster langsam vergrößert und verkleinert, wo es dann entweder zu spät oder zu früh umbricht).

Weiß vielleicht jemand wie man das anpassen kann damit es klappt?

PS: Hab das ganze mal als Beispielprojekt angehängt.
Dateianhänge
MultiLineRadioButton.zip
(3.3 KiB) 68-mal heruntergeladen

Antworten