![]() |
Firemonkey - Tooltip-Componente
Hallo zusammen,
es kommt ja nicht oft vor, dass ich der Meinung bin, etwas veroeffentlichen zu koennen. :-) Wem die Vorgeschichte nicht interessiert, kann gleich zum Hauptthema springen. :-) Vorgeschichte: Ich wollte mir mal wieder ein kleines Programm schreiben (wie so oft). Das Programm sollte fuer mich ein paar kleine 'Gimmicks' haben. Nach langem Suchen und Herumprobieren, war ich mit meinem Ergebnis, was ich mit meinem Kenntnisstand und gefundenen Moeglichkeiten erreichen konnte, nicht sehr zufrieden. Ich habe dann mal einen Blick auf die Firemonkey Demos geworfen, und bin dort fuendig geworden. Ich habe somit vor kurzem angefangen mein Programm mit Firemonkey zu erstellen. Dabei musste ich dann feststellen, dass Firemonkey nicht immer "Vorteile" hat. So auch beim Thema Tooltips. Hauptthema: Tooltips mit Firemonkey. Mit dem Beispiel von Embarcadero war ich nicht sonderlich zufrieden, aber es hat mir gut als Grundlage dienen koennen. Auf Basis des Beispieles habe ich nun eine "eigene" Komponente erstellt, mit der man Tioltips anzeigen lassen kann. Die Komponente besteht aus: Form: durchsichtig Rectangle: hiermit kann das Aussehen gesteuert werden Label: enthaelt den eigentlichen anzuzeigenden Text Timer Delay: stellt die Verzoegerungszeit ein, nach der ein Tooltip angezeigt werden soll Timer Interval: stellt die Zeit ein, wie lange ein Tooltip angezeigt werden soll StringList Controls: enthaelt die Namen der Controls, fuer welche ein Tooltip angezeigt werden soll StringList Tipps: enthaelt die zugehoerigen anzuzeigenden Texte.
Delphi-Quellcode:
Genutzt wird die Komponente zum Beispiel so:
unit FrmToolTip;
interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls, FMX.Objects; type TTooltip = class(TForm) FShape: TRectangle; FDelay: TTimer; FInterval: TTimer; private Elements: TStringList; Tips: TStringList; FLabel: TLabel; FMousePoint: TPointF ; FCounter: Cardinal; FActiveControl: TFmxObject ; FBorderWidth: Single; function GetElementIndex(EName: String): Integer; function GetElementTip(EName: String): String; function GetToolTipText: String; procedure SetToolTipText(const Value: String); procedure ShowDelayOnTimer(Sender: TObject); procedure ShowTimeOnTimer(Sender: TObject); public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure ShowToolTip(AX, AY: Single); procedure AddControlName(const Value: String); procedure AddControlTip(const Value: String); property Text : String read GetToolTipText write SetToolTipText; property BorderWidth : Single read FBorderWidth write FBorderWidth; end; implementation {$R *.fmx} {$region 'Create/Destroy'} constructor TTooltip.Create(AOwner: TComponent); begin inherited; //Elements which will show a tooltip Elements := TStringList.Create; //Tips to display Tips := TStringList.Create; Show; Hide; FLabel := TLabel.Create(AOwner); FLabel.Parent := Self; FLabel.StyleLookup := 'labelstyle'; FLabel.Text := 'FMXToolTip'; if assigned(FLabel.Canvas) then Height := Round(FLabel.Canvas.TextHeight(FLabel.Text)); FLabel.Align := TAlignLayout.alClient; FLabel.TextAlign := TTextAlign.taCenter; FLabel.VertTextAlign := TTextAlign.taCenter; FDelay := TTimer.Create(AOwner); FDelay.OnTimer := ShowDelayOnTimer; FDelay.Enabled := True ; FDelay.Interval := 200; FInterval := TTimer.Create(AOwner); FInterval.OnTimer := ShowTimeOnTimer; FInterval.Enabled := false; FInterval.Interval := 1200; FActiveControl := nil; FCounter := 1000; FBorderWidth := 5; end; destructor TTooltip.Destroy; begin inherited; end; {$endregion 'Create/Destroy'} {$region 'Fill lists'} procedure TTooltip.AddControlName(const Value: String); begin Elements.Add(Value); end; procedure TTooltip.AddControlTip(const Value: String); begin Tips.Add(Value); end; {$endregion 'Fill lists'} {$region 'Get/Set tooltip text'} function TTooltip.GetElementIndex(EName: String): Integer; var i: Integer; begin i := -1; for i := 0 to Elements.Count - 1 do begin if Elements[i] = EName then begin Result := i; break; end; end; end; function TTooltip.GetElementTip(EName: String): String; var i: Integer; begin for i := 0 to Elements.Count - 1 do begin if Elements[i] = EName then begin Result := Tips[i]; break; end; end; end; function TTooltip.GetToolTipText: String; begin Result := FLabel.Text; end; procedure TTooltip.SetToolTipText(const Value: String); begin FLabel.Text := Value ; end; {$endregion 'Get/Set tooltip text'} {$region 'Show tooltip'} procedure TTooltip.ShowToolTip(AX, AY: Single); var PointX: Single; PointY: Single; begin PointX := AX + 5; //+ 5 to leave some space for a more decent look PointY := AY + 5; // dito try Height := Round(FLabel.Canvas.TextHeight(FLabel.Text) + 2 * FBorderWidth); Width := Round(FLabel.Canvas.TextWidth(FLabel.Text) + 2 * FBorderWidth) + 8; if (PointX + Width) > Screen.Size.Width then PointX := PointX - Width - 5; //s. a. if (PointY + Height) > Screen.Size.Height then PointY := PointY - Height - 5; //s. a. Left := Round(PointX); Top := Round(PointY); FDelay.Enabled := false; FInterval.Enabled := true; Show; except on E:Exception do ShowMessage(E.Message); end; end; {$endregion 'Show tooltip'} {$region 'Timer action'} procedure TTooltip.ShowDelayOnTimer; var LActiveControl : IControl; LControl : TControl; LMousePos : TPointF; LObject : IControl ; i: Integer; begin try if Screen.MousePos <> FMousePoint then begin FMousePoint := Screen.MousePos ; FCounter := 0; Hide; end ; Inc(FCounter); case FCounter of 0..2: Hide; 3: begin Text := ''; if Parent is TForm then begin LObject := (Parent as TForm).ObjectAtPoint(FMousePoint) ; if Assigned(LObject) then begin Text := LObject.GetObject.Name; if GetElementIndex(Text) <> -1 then begin Text := GetElementTip(Text); LMousePos := Screen.MousePos; ShowToolTip(LMousePos.X, LMousePos.Y); end; end; end; end; else FCounter := 1000; Hide; end; except on E:Exception do ShowMessage('Error: ' + E.Message); end; end; procedure TTooltip.ShowTimeOnTimer(Sender: TObject); begin FInterval.Enabled := false; FDelay.Enabled := true; //Hide tooltip Hide; end; {$endregion 'Timer action'} end.
Delphi-Quellcode:
Ich hoffe, ich habe soweit alles richtig angegeben, und auch hoffentlich die richtige Forumsrubrik gewaehlt.
uses
....., FrmTooltip; var ... Tooltip : TToolTip; procedure Form1.Show; begin //Erstellen der Tooltip-Komponente Tooltip := TToolTip.Create(Tooltip); //Zuweisen der "Elternform" Tooltip.Parent := Mainform ; //Hinzufuegen von Elementen, fuer die ein Tipp angezeigt werden soll Tooltip.AddControlName('Image_Beispiel'); Tooltip.AddControlName('Edit_Beispiel'); Tooltip.AddControlName('Listbox_Beispiel'); //Hinzufuegen der Texte, welche angezeigt werden sollen Tooltip.AddControlTip('Dies ist der Tip zum Bild Image_Beispiel'); Tooltip.AddControlTip('Dies ist der Tip zur TextBox Edit_Beispiel'); Tooltip.AddControlTip('Dies ist der Tip zur ListBox Listbox_Beispiel'); //Konfiguration der Timer und des Erscheinungsbildes Tooltip.FDelay := 250; //Default = 200 Tooltip.FInterval := 1000; //Default = 1200 Tooltip.FShape.XRadius := 8; //Default = 4 Tooltip.FShape.YRadius := 8; //Default = 4 Tooltip.FShape.Fill.Kind := TBrushKind.bkSolid; //Default = bkGradient Tooltip.FShape.Fill.Color := $FFE0E0E0; end; Vielleicht kann der eine oder andere ja die Komponente gebrauchen. :-) Ich moechte mir hier auch noch einmal bei Embarcadero fuer das Beispiel bedanken. Gruss AnCorr |
AW: Firemonkey - Tooltip-Componente
Ich würde dir empfehlen deine Delphi-Codes auch in [delphi]...[/delphi]-Tags zu packen, damit man den Code besser lesen kann.
Was ich bei der Componente eher unglücklich finde ist, daß es keinen "direkten" Zusammenhang zwischen Element und Tipt gibt. Und vorallem, wie bekommt man den Tipp von einem Element wieder weg oder tausch ihn gegen einen neuen Tipp aus? z.B. (also Kommentar ein Variante es intern zusammenhängend zu speichern/verwalten)
Delphi-Quellcode:
SetTip(Element, Tip: string); // Elements.Value[Element] := Tip;
RemoveTip(Element: string); // Elements.Value[Element] := ''; Wenn die Komponente aber dann mal funktioniert und auch nutzbar ist, dann kannst du sie gern dort mit verlinken: ![]() |
AW: Firemonkey - Tooltip-Componente
Hallo himitsu
Danke fuer die Hinweise und Anregungen! Das ist das erste Mal, dass ich ueberhaupt einen Code veroeffentliche, auch dass es meine erste "selbst" geschriebene Komponente ist. Zu 1: musss ich hierfuer die Tags [CODE]... durch [DELPHI] ersetzen? Zu 2: ein Entfernen von Tips war fuer mich eigentlich nicht vorgesehen. Ich hatte bisher noch nicht den Fall, dass ich zur Laufzeit einen Tip wieder aendern bzw. looeschen musste. Aber ich werde das bei Gelegenheit noch einbauen. :-) Was meinst du mit "Wenn die Komponente mal funktioniert"? Bei mir funktioniert sie ganz gut. Gibt es irgendwelche Fehler? Fuer Anregungen und Verbesserungsvorschlaege etc. habe ich immer ein offenes Ohr. :-) Gruss AnCorr |
AW: Firemonkey - Tooltip-Componente
[CODE] ist schonmal besser als nix, aber [DELPHI] stellt auch noch eine CodeFormatierung bereit ... ähnlich der in deinem Delphi.
Siehe mein Codebeispiel. Du kannst hier in diesem Unterforum deinen Beitrag 24 Stunden lang bearbeiten. (in "Software-Projekte der Mitglieder" ist es auch möglich unbegrenzt lang/oft den ersten Beitrag zu bearbeiten, um immer das Aktuellste direkt dort zu zeigen und anzuhängen) Was gerne mal gemacht wird, ist den Hint an den Inahlt anzupassen und dafür müsste man ihn verändern können. Nja, wenn es dann auch Andere nutzen können, also auch die, welche ihre Hints gern ändern wollen, dann könnte man den Code auch an noch mehr Programmierer weitergeben ... z.B. über das QC und nicht nur im Delphi. Ich hatte auch mal versucht Hints zu basteln, allerdings sind es da keine eigenen Fenster und die Hints werden nur als "Panel" in das jeweilige Fenster reingemalt. ![]() Wenn du deine Komponente von TComponent ableitest und die Form als Unterkomponente zur Laufzeit innerhalb dieser Klasse erzeugst, dann könnte man deine Komponente auch im Delphi registieren, wie einen TTimer auf die Form ziehen und im OI bearbeiten. z.B. wie das Lines von einem Memo. Der Zugriff über Elements.Value würde dann im Default-Editor von TStrings so aussehen:
Code:
Image_Beispiel=Dies ist der Tip zum Bild Image_Beispiel
Edit_Beispiel=Dies ist der Tip zur TextBox Edit_Beispiel |
AW: Firemonkey - Tooltip-Componente
Hallo,
danke fuer die Hilfe! Die Formatierung habe ich schon mal aendern koennen. :-) "Im Grunde genommen weiss ich was du meinst", aber ich denke, so schnell bekomme ich das nicht hin. Ich kenne Pascal/Delphi zwar schon seit mehr als 20 Jahren, programmiere aber immer wieder nur zum Spass kleinere Programme/Tools (so wie auch zur Zeit). Ich muss mir das mit dem Registrieren etc. mal anschauen und dann einbauen. Auch wuerde ich dann die Zuweisungen noch aendern und deine Vorschlaege mit einarbeiten. Gruss AnCorr |
AW: Firemonkey - Tooltip-Componente
Wenn du die Liste als Published-Property mit TStrings/TStringList freigibst (nur
Delphi-Quellcode:
und kein
read
Delphi-Quellcode:
, bzw. das Write nur als Assign an die StringList übergeben und nicht auf die Variable zuweisen), dann bekommst du den Standard-Property-Editor für TStrings und brauchst dich nicht um einen eigenen Editor zu kümmern.
write
Und das Registrieren ist recht einfach:
Delphi-Quellcode:
Für genauere Infos und wie man auch ein eigens Icon angibt, dafür sollten sich massig Tutorials für
procedure register;
implementation procedure Register; begin RegisterComponents('Zusätzlich', [TTooltip]); end; ![]() |
AW: Firemonkey - Tooltip-Componente
Hi,
ich habe den Code mal so abgeaendert, dass nun auch Hinweise entfernt oder geaendert werden koennen. Ebenso habe ich, nachdem ich einen Teil des Themas ueber deine Komponente gelesen habe, das genutzte Label auch oeffentlich gemacht, damit auch dieses nach eigenen Wuenschen formatiert werden kann. :-) Kann ich den Code einfach gegen den bisherigen austauschen, oder soll ich diesen neu (zusaetzlich) einstellen? Das mit dem Erzeugen der Form innerhalb der Komponente versuche ich noch einzubauen, ebenso wie die Routine zum Registrieren. Danke fuer die Hilfe! Gruss AnCorr (Eigentlich wollte ich ja an meinem Programm weiterarbeiten, aber das Thema "Komponente" reizt mich nun auch :-) ) |
AW: Firemonkey - Tooltip-Componente
ich würde die beiden prozeduren
Delphi-Quellcode:
und
AddControlName()
Delphi-Quellcode:
zu einer einzigen Prozedur mit 2 Parametern zusammenfassen.
AddControlTip()
Dein Anwendungbeispiel sieht dann so aus:
Delphi-Quellcode:
Damit wird die Schnittstelle klarer und es wird verhindert, dass Controls und Tips auseinanderlaufen.
//Hinzufuegen der Controls & Texte, welche angezeigt werden sollen
Tooltip.AddControlTip(Image_Beispiel, 'Dies ist der Tip zum Bild Image_Beispiel'); Tooltip.AddControlTip(Edit_Beispiel, 'Dies ist der Tip zur TextBox Edit_Beispiel'); Tooltip.AddControlTip(Listbox_Beispiel, 'Dies ist der Tip zur ListBox Listbox_Beispiel'); // der Tooltip für ein Control kann auch nachträglich geändert werden Tooltip.AddControlTip(Edit_Beispiel, 'Geänderter Tip zur TextBox Edit_Beispiel'); // man kann sogar den Tooltip wieder entfernen Tooltip.AddControlTip(Listbox_Beispiel, '');
Delphi-Quellcode:
Das Feld
// die neue Prozedur
procedure TTooltip.AddControlTip(control: Tcontrol; const ToolTip: String); var i : integer; begin i := Tips.IndexOfObject(control); // prüfe ob Control schon in Liste if i <> -1 then begin if ToolTip = '' then Tips.Delete(i) // lösche bestehenden Eintrag in der Liste else Tips.Strings[i] := ToolTip // ändere Tooltip für gefundenes Control end else if Assigned(control) then Tips.AddObject(ToolTip, control); // Control & Tooltip anhängen end;
Delphi-Quellcode:
kann dann komplett entfallen.
Elements: TStringList
In der Procedure procedure TTooltip.ShowDelayOnTimer müssen dann natürlich Veränderungen vorgenommen werden.
Delphi-Quellcode:
Die Hilfsprozeduren
LObject := (Parent as TForm).ObjectAtPoint(FMousePoint) ;
idx := Tips.IndexOfObject(LObject); if idx <> -1 then // prüfe ob das Control in der Liste ist begin Text := Tips.Strings[idx]; // Hole den Tooltip zu dem Control LMousePos := Screen.MousePos; ShowToolTip(LMousePos.X, LMousePos.Y); end;
Delphi-Quellcode:
und
GetElementIndex()
Delphi-Quellcode:
werden nicht mehr gebraucht.
GetElementTip()
|
AW: Firemonkey - Tooltip-Componente
Hallo sx2008,
die beiden Routinen habe ich schon zu einer zusammengefasst, so wie es himitsu schon vorgeschlagen hat. Die Stringliste habe ich allerdings noch drin. Den geanderten Code habe ich noch nicht hier eingebracht, weil ich noch nicht weiss, ob ich nun den bisherigen einfach ueberschreiben soll, oder als neuen hier anhaengen soll. Zwischenzeitlich habe ich mal versucht, daraus eine "richtige" Klasse/Komponente zu machen, aber das hat nicht so ganz funktioniert. Ich kann ein Paket erzeugen und installieren, aber beim Verwenden wird die Klasse in ihre Einzelteile "zerlegt". Das heisst, die beiden Timer, das Label und das Rechteck werden auf die "Hauptform" gelegt, und sind alle "namenlos". Ich muss diese dann wieder dem ToolTip-Objekt zuordnen und neu benennen. Ein Klick auf das ToolTip-Objekt erzeugt dann gar einen "Zugriffsfehler" in einem der fmx..19.bpl Pakete (habe das Paket wieder entfernt, deshalb kann ich den Fehler im Moment nicht mehr reproduzieren). Eine Form als Klasse zu erstellen scheint mit Firemonkey wohl nicht ganz so einfach zu sein. Gruss AnCorr |
AW: Firemonkey - Tooltip-Componente
Wäre es nicht besser, wenn man den Beitrag unter Projekte verschiebt, damit der Beitragsersteller die Änderungen im ersten Beitrag einpflegen kann, eventuell auch mit Anhang ?
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:15 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