Mehrzeiliger Speedbutton funktioniert nicht

Für Fragen von Einsteigern und Programmieranfängern...
Inventio
Beiträge: 39
Registriert: So 21. Mär 2010, 14:00

Mehrzeiliger Speedbutton funktioniert nicht

Beitrag von Inventio »

Hallo,
ich habe vor einigen Tagen nachgefragt, wie ich mehrzeilige Buttons realisieren kann und wurde auf die Speedbuttons verwiesen. Dies klappt auf meinem Rechner (Win7 64bit) auch wunderbar. Jetzt habe ich das Programm an einen Kumpel weitergegeben und bei ihm wird der Inhalt des Buttons nicht mehrzeilig dargestellt. Er benutzt Win Vista 32 bit.
Kann es sein, dass dieses "Trick" mit Speedbuttons einfach nicht auf seinem Betriebssystem funktioniert ?


Lg Inventio

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

Re: Mehrzeiliger Speedbutton funktioniert nicht

Beitrag von theo »

Bei sowas ist "gegen den Strom schwimmen" immer problematisch.
Kennst du eine professionelle Software, wo klassische Buttons mehrzeilig sind? (Firefox, Openoffice...) Das würde mich interessieren.
Mach's einfach anders, mit Label, Hint oder Logo.

kirchfritz
Beiträge: 172
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win10 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Mehrzeiliger Speedbutton funktioniert nicht

Beitrag von kirchfritz »

Meine Antwort kommt sehr spät, aber mein Vorredner interessiert sich für professionelle Software mit mehrzeiligen Buttons:
Microsoft Outlook ist doch ein schönes Beispiel für den intensiven Einsatz mehrzeiliger Buttons:
Guckst Du hier: https://www.screencast.com/t/PAkW3Lv1K

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

Re: Mehrzeiliger Speedbutton funktioniert nicht

Beitrag von wp_xyz »

Das sind keine Speedbuttons, sondern ein komplett anderes Control (Ribbon). Unter Lazarus kommt dem die SpkToolbar am nächsten (im Online-Package-Manager). Und ich meine, es gibt auch unter den BGRAControls (oder wie auch immer die genau heißen) eine Variante davon.

Benutzeravatar
gladio
Beiträge: 217
Registriert: Sa 21. Jun 2014, 06:15
OS, Lazarus, FPC: Win10-64 - aktuelle Lazarus/FPC Standard-Edition
CPU-Target: 64Bit
Wohnort: Rügen

Re: Mehrzeiliger Speedbutton funktioniert nicht

Beitrag von gladio »

Man muss nicht alles nachmachen.
Die Menüs in MS-Office etc. sind grausam.

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Mehrzeiliger Speedbutton funktioniert nicht

Beitrag von Winni »

Hi!

Selber machen:

Schreibe Deine mehrzeilige Caption auf den Canvas des SpeedButton.

Winni

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

Re: Mehrzeiliger Speedbutton funktioniert nicht

Beitrag von wp_xyz »

Aber nimm dafür das OnPaint Event des Speedbutton:

Code: Alles auswählen

procedure TForm1.SpeedButton3Paint(Sender: TObject);
var
  ts: TTextStyle;
  R: TRect;
begin
  R := Rect(0, 0, SpeedButton3.Width, SpeedButton3.Height);
  with SpeedButton3.Canvas do
  begin
    ts := TextStyle;
    ts.Wordbreak := true;
    ts.SingleLine := false;
    ts.Alignment := taCenter;
    ts.Layout := tlCenter;
    TextRect(R, 0, 0, 'Hallo' + LineEnding + 'Welt', ts);
  end;
end;
Die Caption des SpeedButton muss in diesem Code leer sein.

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Mehrzeiliger Speedbutton funktioniert nicht

Beitrag von Winni »

Hi!

Es gibt noch einen Trick, wie man die Caption des SpeedButtons doch benutzen kann:

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
var cap  : String;
....
cap := SpeedButton1.Caption;
SpeedButton1.Tag := PtrInt(@cap);
SpeedButton1.Caption := '';   
....

Und in der oben gezeigten procedure SpeedButton1Paint machst Du

Code: Alles auswählen

var cap: string;
P: Pstring; 
.....
P := Pointer(SpeedButton1.Tag);
cap := P^;
TextRect(R, 0, 0, cap , ts);
Dies ist also nebenbei ein Beispiel, wie man die Property Tag aller Componenten sinnvoll nutzen kann.


Winni

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

Re: Mehrzeiliger Speedbutton funktioniert nicht

Beitrag von Warf »

Winni hat geschrieben:
Fr 4. Feb 2022, 15:36

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
var cap  : String;
....
cap := SpeedButton1.Caption;
SpeedButton1.Tag := PtrInt(@cap);
SpeedButton1.Caption := '';   
....
Und in der oben gezeigten procedure SpeedButton1Paint machst Du

Code: Alles auswählen

var cap: string;
P: Pstring; 
.....
P := Pointer(SpeedButton1.Tag);
cap := P^;
TextRect(R, 0, 0, cap , ts);
Dies ist also nebenbei ein Beispiel, wie man die Property Tag aller Componenten sinnvoll nutzen kann.
Den pointer einer Lokalen variable in den Tag zu schreiben ist wahrscheinlich das einzige Beispiel wie man den Tag einer Komponente nicht sinnvoll nutzen kann. Sobald die Funktion endet ist das einfach nur noch ne Tretmine die darauf wartet hoch zu gehen wenn man das nächste mal drauf zugreift.

Was du machen kannst ist:

Code: Alles auswählen

PString(@SpeedButton1.Tag)^ := SpeedButton1.Caption;
Was den Tag im grunde als String variable fungieren lässt und damit die Referenzzählung von Strings berücksichtigt, aber den Pointer einer Property zu nehmen ist extrem unsauber und sehr instabil, da die umstellung auf getter das direkt zerschießt (MMn. ist das mehr ein Bug als ein Feature)

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Mehrzeiliger Speedbutton funktioniert nicht

Beitrag von Winni »

Hi!

1000fach benutzt ohne Probleme.

Winni

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

Re: Mehrzeiliger Speedbutton funktioniert nicht

Beitrag von Warf »

Winni hat geschrieben:
Fr 4. Feb 2022, 20:04
1000fach benutzt ohne Probleme.
Dann würde ich mal ganz stark deine Tests infrage stellen. Ganz einfaches Beispiel, 2 Buttons:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject); 
var
  Cap: String;
begin
  Cap := 'Tausend mal Berührt, tausendmal ist nichts passiert';
  Button1.Tag := PtrInt(@Cap);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  s: String;
begin
  s := 'Tausend und eine Nacht und es hat zoom gemacht';
  ShowMessage(PString(Button1.Tag)^);
end;  
Also bei mir machts zoom

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

Re: Mehrzeiliger Speedbutton funktioniert nicht

Beitrag von wp_xyz »

Inventio hat geschrieben:
So 25. Nov 2012, 16:35
ich habe vor einigen Tagen nachgefragt, wie ich mehrzeilige Buttons realisieren kann und wurde auf die Speedbuttons verwiesen. Dies klappt auf meinem Rechner (Win7 64bit) auch wunderbar. Jetzt habe ich das Programm an einen Kumpel weitergegeben und bei ihm wird der Inhalt des Buttons nicht mehrzeilig dargestellt. Er benutzt Win Vista 32 bit.
Kann es sein, dass dieses "Trick" mit Speedbuttons einfach nicht auf seinem Betriebssystem funktioniert ?
Hab' das gerade auf diversen Windows-Versionen ausprobiert (Vista habe ich allerdings nicht), und muss feststellen, dass auch mit Win 11, Win 7, Win XP und Win 2000 die Beschriftung eines Standard-SpeedButtons, in der ein Zeilenumbruch eincodiert ist, zweizeilig erscheint. Alles 32 Bit.

Vielleicht liegt das Missverständnis darin, dass der Zeilenumbruch nicht automatisch erfolgt, sondern dass an der Stelle des Umbruchs schon ein LineEnding in der Caption enthalten sein muss, den man allerdings nur im Quellcode eingeben kann

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
begin
  SpeedButton1.Caption := 'Hallo' + LineEnding + 'Welt';
end; 

kirchfritz
Beiträge: 172
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win10 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Mehrzeiliger Speedbutton funktioniert nicht

Beitrag von kirchfritz »

@wp_xyz

Dass

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
begin
  SpeedButton1.Caption := 'Hallo' + LineEnding + 'Welt';
end; 
die SpeedButton.Caption umbrechen lässt, ist klar.
Nicht klar ist, warum die mehrzeilige Caption dann nicht zentriert, ist, wenn beim SpeedButton die Layout-Eigenschaft auf blGlyphTop gesetzt ist.
Dann wir zwar die Caption umgebrochen, aber sie wird linksbündig dargestellt. Und das ist lästig!

kirchfritz
Beiträge: 172
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win10 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Mehrzeiliger Speedbutton funktioniert nicht

Beitrag von kirchfritz »

Warf hat geschrieben:
Fr 4. Feb 2022, 19:06
Winni hat geschrieben:
Fr 4. Feb 2022, 15:36

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
var cap  : String;
....
cap := SpeedButton1.Caption;
SpeedButton1.Tag := PtrInt(@cap);
SpeedButton1.Caption := '';   
....
Und in der oben gezeigten procedure SpeedButton1Paint machst Du

Code: Alles auswählen

var cap: string;
P: Pstring; 
.....
P := Pointer(SpeedButton1.Tag);
cap := P^;
TextRect(R, 0, 0, cap , ts);
Dies ist also nebenbei ein Beispiel, wie man die Property Tag aller Componenten sinnvoll nutzen kann.
Den pointer einer Lokalen variable in den Tag zu schreiben ist wahrscheinlich das einzige Beispiel wie man den Tag einer Komponente nicht sinnvoll nutzen kann. Sobald die Funktion endet ist das einfach nur noch ne Tretmine die darauf wartet hoch zu gehen wenn man das nächste mal drauf zugreift.

Was du machen kannst ist:

Code: Alles auswählen

PString(@SpeedButton1.Tag)^ := SpeedButton1.Caption;
Was den Tag im grunde als String variable fungieren lässt und damit die Referenzzählung von Strings berücksichtigt, aber den Pointer einer Property zu nehmen ist extrem unsauber und sehr instabil, da die umstellung auf getter das direkt zerschießt (MMn. ist das mehr ein Bug als ein Feature)
Ich habe das jetzt bei zwei SpeedButtons, die eine identische OnPaintRoutine verwenden, so gelöst, und es funktioniert wunderbar.:

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
begin
  PString(@SpeedButton1.Tag)^ := SpeedButton1.Caption;
  SpeedButton1.Caption := '';
  PString(@SpeedButton2.Tag)^ := SpeedButton2.Caption;
  SpeedButton2.Caption := '';
end;

procedure TForm1.SpeedButtonPaint(Sender: TObject);
var
  ts: TTextStyle;
  R: TRect;
begin
  R := Rect(0, 0, TSpeedButton(Sender).Width, TSpeedButton(Sender).Height);
  with TSpeedButton(Sender).Canvas do
  begin
    ts := TextStyle;
    ts.Wordbreak := true;
    ts.SingleLine := false;
    ts.Alignment := taCenter;
    ts.Layout := tlTop;
    TextRect(R, 0, 40, PString(@TSpeedButton(Sender).Tag)^, ts);
  end;
end;   

kirchfritz
Beiträge: 172
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win10 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Mehrzeiliger Speedbutton funktioniert nicht

Beitrag von kirchfritz »

So siehts jetzt aus:
https://www.screencast.com/t/WFUkcmjWRdM
2022-02-07_09-37-31.png
2022-02-07_09-37-31.png (8.82 KiB) 1349 mal betrachtet

Antworten