Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi TButton mit zwei Captions und unterschiedlichem Font (https://www.delphipraxis.net/144734-tbutton-mit-zwei-captions-und-unterschiedlichem-font.html)

Phoner 15. Dez 2009 13:19


TButton mit zwei Captions und unterschiedlichem Font
 
Hallo,

ich habe zwei TLabel-Komponenten als Unter-Komponenten eines TButtons definiert. Auf diese Art kann ich zwei Caption-Zeilen simulieren, jeweils mit unterschiedlichem Font. Rein optisch sieht das erst mal OK aus.
Klicke ich den Button jedoch so an, dass ich ein drüber liegendes Label treffe, so sehe ich kein optisches Feedback des Buttons.
Meine Frage lautet also: Wie kann ich eine Control visuell sichtbar schalten, aber alle Mausoperationen sollen direkt vom Parent (hier dem TButton) behandelt werden. Klar kann ich das OnClick-Ereignis entsprechend auf die gleiche Funktion setzen, aber mir fehlt die optische Umsetzung, dass der Button gedrückt wird, wenn ich ein darüber liegendes Control treffe.

Oder fällt jemand eine andere Möglichkeit ein, einen TButton mit zwei Captions und jeweils unterschiedlichem Font zu erstellen? Ich möchte keine Bitmaps benutzen.

himitsu 15. Dez 2009 13:31

Re: TButton mit zwei Captions und unterschiedlichem Font
 
Warum zeichnest du dann den Text einfach nicht selber?

Ansonsten mußt du in den Labels die Windowsbotschaften (das Klicken) abfangen, an den Button weiterleiten und eventuell noch die Klickposition umrechnen.

shmia 15. Dez 2009 13:39

Re: TButton mit zwei Captions und unterschiedlichem Font
 
Zitat:

Zitat von Phoner
Klar kann ich das OnClick-Ereignis entsprechend auf die gleiche Funktion setzen, aber mir fehlt die optische Umsetzung, dass der Button gedrückt wird, wenn ich ein darüber liegendes Control treffe.

Nicht auf den gleichen Eventhandler setzen sondern auf:
Delphi-Quellcode:
proecdure TMyObscureDoubleLabelButton.LabelClicked(Sender:TObject);
begin
   self.Click;
end;

Phoner 15. Dez 2009 14:06

Re: TButton mit zwei Captions und unterschiedlichem Font
 
@himitsu
Wie zeichne ich denn den Text direkt drauf? Fleucht da irgendwo ein Sample rum?

@shmia
Ja, da mag schöner sein, aber prinzipiell ist das Auswerten des Events nicht das Problem.

himitsu 15. Dez 2009 14:14

Re: TButton mit zwei Captions und unterschiedlichem Font
 
Standardmäßig hat ein Button ja kein OnPaint-Ereignis, aber notfalls könnt man das umgehen.

- man zeichne ein Bild mit dem gewünschten Text
- lege es in einer ImageList ab
- und weise es dem Button zu

dieses Bild kann man auch live, z.B. im OnCreate und bei Änderung der Captions zeichnen
und halte die ImageList als Subkomponente des Buttons.

shmia 15. Dez 2009 14:44

Re: TButton mit zwei Captions und unterschiedlichem Font
 
Zitat:

Zitat von Phoner
@shmia
Ja, da mag schöner sein, aber prinzipiell ist das Auswerten des Events nicht das Problem.

Es geht doch gar nicht um Schönheit, sondern um Funktionalität.
Was wäre, wenn bei deinem Button Enabled=False wäre.
Dann würde ein Klick auf das Label das Event des Buttons aufrufen, was bestimmt nicht erwünscht ist.
Durch Aufruf der Click-Methode wird genau das Gleiche gemacht, das auch passiert wenn man den Button per Maus anklickt.
In der OH steht auch, dass zusätzlich das Modal-Result des Formulars gesetzt wird.
Ausserdem möchtest du den Button vielleicht auch zusammen mit Actions einsetzen.
Auch hier stellt die Click-Methode sicher, dass die Action über den ActionLink ausgeführt wird.

HJay 16. Dez 2009 19:28

Re: TButton mit zwei Captions und unterschiedlichem Font
 
Sehr interessantes Thema! Ich versuche mich gerade in Vererbung und Objekterzeugung einzuarbeiten und bin auch an einer Lösung interessiert.

Erste Idee wäre gewesen:

Delphi-Quellcode:
TMyButton = class(TButton)
protected
  procedure Paint(var Message: TMessage); message WM_PAINT;
public
  UpperLine : String;
  LowerLine : String;
end;

procedure TMyButton.Paint(var Message: TMessage);
begin
  Canvas.TextOut(0, 0, UpperLine);  // Canvas gibt es aber leider nicht...
  Canvas.TextOut(0, 12, LowerLine);
end;
1) Würde das funktionieren mit WM_PAINT?

2) Nur leider hat TButton kein Canvas. Kann man mit dem "Handle" irgendwie auf die Fläche des Buttons zeichnen/schreiben? Falls ja, wie geht das?

3) Oder noch anders: Kann man irgendwie auf elegante Art ein Canvas in der Methode "nachrüsten", also bei Create erzeugen und als TCanvas zur Verfügung stellen?

Ich bin gespannt!

HJay 18. Dez 2009 19:02

Re: TButton mit zwei Captions und unterschiedlichem Font
 
Ich habe Fortschritte gemacht, aber leider noch ein Problem: Die beiden Captions werden korrekt gezeichnet, aber nachdem man draufgedrückt hat, bleibt der Button leer. Sobald die Form eine andere Paint-Message erhält, zeichnet er sich wieder. Was habe ich vergessen? Auf welche Message müsste ich noch reagieren?

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

type
  TMyButton = class(TButton)
  protected
    procedure Paint(var Msg: TMessage); message WM_PAINT;
  private
    FCanvas: TCanvas;
  public
    CaptionTop : String;
    CaptionBottom : String;

    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

    property Canvas: TCanvas read FCanvas;
  end;

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    MyButton : TMyButton;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TMyButton }

constructor TMyButton.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Parent := AOwner as TWinControl;
  FCanvas := TCanvas.Create;
  FCanvas.Handle := GetDC(Self.Handle);;
end;

destructor TMyButton.Destroy;
begin
  FCanvas.Free;
  inherited;
end;

procedure TMyButton.Paint(var Msg: TMessage);
begin
  inherited;
  Canvas.Pen.Color := clBlack;
  Canvas.Brush.Style := bsClear;
  Canvas.TextOut(2, 2, CaptionTop);
  Canvas.Font.Style := Canvas.Font.Style + [fsBold]; // zweite Zeile anders formatiert
  Canvas.Textout(2, 2 + Canvas.TextHeight(CaptionTop), CaptionBottom);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  MyButton := TMyButton.Create(Self);
  MyButton.Left  := 16;
  MyButton.Top   := 48;
  MyButton.Height := 48;
  MyButton.CaptionTop   := 'upper text';
  MyButton.CaptionBottom := 'lower text';
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  MyButton.Free;
  inherited;
end;

end.

HJay 2. Jan 2010 13:48

Re: TButton mit zwei Captions und unterschiedlichem Font
 
Hat keiner von den Kennern hier eine Lösung? Ist echt schade, dass es FAST geht, aber dann an so einer Kleinigkeit scheitert. Wäre echt dankbar, wenn jemand noch einmal einen Blick drauf werfen könnte, denn das gleich Prinzip wäre für viele andere Komponenten ohne eigenen Canvas ja auch brauchbar!

Danke im voraus! (was ein Danke im nachhinein nicht ausschließen soll :-)

SirThornberry 2. Jan 2010 14:10

Re: TButton mit zwei Captions und unterschiedlichem Font
 
Mir fällt auf das du im OnCreate einfach den Parent setzt und den Owner auf WinControl castest.
Das ist der völlig falsche Weg. Wenn der Owner zum Beispiel kein WinControl ist knallt es. Oder wenn der Owner noch keinen Parent hat wird in aller Regel das Handle auch noch nicht existieren und somit wird auch der Button noch kein Handle haben etc.
Was spricht dagegen das Canvas-Handle erst im OnPaint zu besorgen?

HJay 2. Jan 2010 14:41

Re: TButton mit zwei Captions und unterschiedlichem Font
 
Ja, könnte man auch jedesmal im OnPaint machen. Werde ich mal ändern, obwohl ich es elegant fand, es nur einmal zu machen. Der Button soll ja auch nur auf Formularen oder anderen WinControls liegen.

Leider hat das aber nichts mit dem Problem zu tun, dass der Button zwar richtig gezeichnet wird und über TCanvas angesprochen werden kann, jedoch nach dem Drücken die Paint-Routine nicht aufgerufen wird. Erst wenn man zwischen Fenstern hin-und-her clickt oder so, wird wieder ein Paint empfangen und der Button wieder korrekt dargestellt. Da muss ich irgendwas vergessen habe, ich komme aber nicht drauf.

Garfield 2. Jan 2010 18:51

Re: TButton mit zwei Captions und unterschiedlichem Font
 
Ich würde dafür einen TSpeedButton modifizieren. Allerdings wird dabei alles in TBitmaps gezeichnet, wobei dann beim OnPaint jeweils das entsprechende zur Anzeige kommt.

HJay 2. Jan 2010 19:41

Re: TButton mit zwei Captions und unterschiedlichem Font
 
Hallo Garfield! Ja, ich bin auf die Frage ja nur "aufgesprungen", weil mich das Thema interessierte. Mir geht es eigentlich nur ganz allgemein darum, wie man auf Controls, die keinen Canvas haben, etwas zeichnen kann. Das klappt ja auch schon fast, nur eben nicht vollständig. Das finde ich ärgerlich und komme mir blöde vor. OnPaint wird ausgeführt, aber anscheinend reicht das nicht, um alle relevanten Messages auszuwerten. Ich hatte gehofft, einer der Profis hier, weiß auf Anhieb, was ich vergesse...

Garfield 3. Jan 2010 09:31

Re: TButton mit zwei Captions und unterschiedlichem Font
 
In dem Source oben hast Du die private Variable FCanvas, im Paint verwendest Du jedoch Canvas.

Wenn Dir Messages fehlen, sieh einfach in den Sourcen zu TButton oder TSpeedButton nach, welche es dort gibt. Du kannst die Komponenten auch einfach in eine eigene Unit kopieren, umbenennen und dann schauen, welche Messages abgearbeitet werden.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:17 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