Erstellen von Kurzhinweisen für die Metropolis-UI
Nach oben zu Entwickeln von Metropolis-UI-Anwendungen
Ein Kurzhinweis im Metropolis-UI-Stil ist ein Popup-Fenster, in dem hilfeähnliche Informationen angezeigt werden, wenn die Maus oder das Touch-Gerät über das Steuerelement geführt wird oder das Steuerelement berührt. In diesem Tutorial wird das Erstellen und Verwenden eines Kurzhinweises mit FireMonkey erläutert.
Erstellen eines neuen FireMonkey-Projekts:
- Erstellen Sie eine neue Desktop-Anwendung für die Metropolis-UI:
- Für Delphi: Datei > Neu > FireMonkey-Desktop-Anwendung für Metropolis-UI - Delphi > Leere Desktop-Anwendung für Metropolis-UI.
- Für C++: Datei > Neu > FireMonkey-Desktop-Anwendung für Metropolis-UI - C++ > Leere Desktop-Anwendung für Metropolis-UI.
- Speichern Sie das Projekt.
Definieren des ToolTip-Klassenobjekts
Erstellen Sie eine neue TToolTipPanel-Klasse für die Anwendung.
Führen Sie in Ihrer Unit die folgenden Schritte aus:
- 1. Fügen Sie die folgenden Units in den uses-Abschnitt ein:
- Delphi:
uses
FMX.Edit;
- C++:
- Fügen Sie in der Header-Datei (.h-Datei) den folgenden Code hinzu:
#include <FMX.Edit.hpp>
- 2. Definieren Sie die von TPanel abgeleitete Klasse TToolTipPanel.
- Delphi:
TToolTipPanel = class(TPanel)
- C++: Definieren Sie diese neue Klasse in der Header-Datei (.h-Datei):
class TToolTipPanel : public TPanel {
//class definition goes here
}
- 3. Fügen Sie ein TLabel als private-Feld hinzu, um Text für den Kurzhinweis hinzuzufügen: FLabel. Definieren Sie die public-Eigenschaft Text zusammen mit den Getter- und Setter-Funktionen der Eigenschaft Text, um auf den Text des Kurzhinweises zuzugreifen.
- Delphi:
type
TToolTipPanel = class(TPanel)
private
FLabel: TLabel;
function GetToolTipText: string;
procedure SetToolTipText(const Value: string);
public
property Text: string read GetToolTipText write SetToolTipText;
end;
- C++:
- Fügen Sie in der Header-Datei (.h-Datei) den folgenden Code hinzu:
class TToolTipPanel : public TPanel {
private:
TLabel *FLabel;
UnicodeString _fastcall GetToolTipText();
void _fastcall SetToolTipText (const UnicodeString Value);
public:
__published:
__property UnicodeString Text = {read = GetToolTipText, write = SetToolTipText};
};
- 4. Implementieren Sie die Getter- und Setter-Funktionen der Eigenschaft Text wie folgt:
function TToolTipPanel.GetToolTipText: string;
begin
Result := FLabel.Text;
end;
procedure TToolTipPanel.SetToolTipText(const Value: string);
begin
FLabel.Text := Value ;
end;
- C++:
- Fügen Sie in der CPP-Datei den folgenden Code hinzu:
UnicodeString _fastcall TToolTipPanel::GetToolTipText() {
return FLabel->Text;
}
// ---------------------------------------------------------------------------
void _fastcall TToolTipPanel::SetToolTipText(const UnicodeString Value) {
FLabel->Text = Value;
}
- 5. Fügen Sie der Klasse TToolTipPanel zusätzlich zu den oben hinzugefügten die folgenden private-Member hinzu:
- Delphi:
private
FMousePoint : TPointF; //keeps the current position for the mouse cursor
FActiveControl : TFmxObject; //keeps the current active control for which the tooltip is displayed
FTimer : TTimer; //the timer is used to decide when, in time, the tooltip is displayed and for how long,
// for the FActiveControl
FCounter : Cardinal;//keeps a counter used on timer execution
FOnlyInputFields : Boolean ; //this flag is used to decides if the tooltip is displayed only for
// input controls
procedure OnTimer(Sender: TObject); //define the OnTime event handler for the FTimer
- C++:
- Fügen Sie in der Header-Datei (.h-Datei) der Klasse TToolTipPanel den folgenden Code hinzu:
TPointF FMousePoint;
TFmxObject *FActiveControl;
TTimer *FTimer;
unsigned FCounter;
bool FOnlyInputFields;
void _fastcall OnTimer (TObject *Sender);
- So stellen Sie das Flag FOnlyInputFields bereit:
- Delphi: Fügen Sie die public-Eigenschaft OnlyInputFields wie folgt hinzu:
public
property OnlyInputFields : Boolean read FOnlyInputFields write FOnlyInputFields;
- C++: Fügen Sie OnlyInputFields wie folgt als published-Eigenschaft hinzu:
__property bool OnlyInputFields = {read = FOnlyInputFields, write = FOnlyInputFields };
- 6. Fügen Sie für ein ansprechendes Design das private-Feld FBorderWidth und die public-Eigenschaft BorderWidth hinzu, um die Breite der Ränder des Kurzhinweises festzulegen und zu ermitteln. Die Ränder werden bei der Anzeige des Kurzhinweises berücksichtigt.
- Delphi:
private
FBorderWidth : Single;
public
property BorderWidth : Single read FBorderWidth write FBorderWidth;
- C++:
- Fügen Sie in der Header-Datei (.h-Datei) der Klasse TToolTipPanel den folgenden Code hinzu:
private:
float FBorderWidth;
__published:
__property float BorderWidth = {read = FBorderWidth, write = FBorderWidth };
- 7. Definieren und implementieren Sie den Konstruktor und den Destruktor für die Klasse TToolTipPanel wie folgt:
-
- Deklaration
-
-
-
- Delphi:
-
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
-
-
- C++:
-
- Fügen Sie in der Header-Datei (.h-Datei) der Klasse TToolTipPanel den folgenden Code hinzu:
-
- C++:
-
public:
__fastcall TToolTipPanel(TComponent* Owner);
__fastcall virtual ~TToolTipPanel(void);
-
-
- Implementierung
-
-
-
- Delphi:
-
constructor TToolTipPanel.Create(AOwner: TComponent);
begin
inherited; //inherits the behavior from TPanel
Visible := False; //initially, the tootltip is not visible
StyleLookup := 'tooltippanel'; // sets the name of the ToolTip style
//initialize FLabel
FLabel := TLabel.Create(AOwner);
FLabel.Parent := Self;
FLabel.StyleLookup := 'tooltiplabel';
FLabel.Text := Self.ToString;
if assigned(FLabel.Canvas) then
Height := FLabel.Canvas.TextHeight(FLabel.Text);
FLabel.Align := TAlignLayout.Client;
FLabel.TextAlign := TTextAlign.Center;
FLabel.VertTextAlign := TTextAlign.Center;
//initialize FTimer
FTimer := TTimer.Create(AOwner);
FTimer.OnTimer := OnTimer;
FTimer.Enabled := True;
FTimer.Interval := 500;
FActiveControl := nil; //initially, there is no control for which to display the tootltip
FCounter := 1000; //FCounter is initially set to a high value
FBorderWidth := 10; //an initial value for the tooltip borders
end;
destructor TToolTipPanel.Destroy;
begin
inherited;
end;
-
-
- C++:
- Fügen Sie in der CPP-Datei der Klasse TToolTipPanel den folgenden Code hinzu:
- C++:
-
__fastcall TToolTipPanel::TToolTipPanel(TComponent* Owner) : TPanel(Owner){
Visible = False;
StyleLookup = "tooltippanel";
FLabel = new TLabel(this);
FLabel->Parent = this;
FLabel->StyleLookup = "tooltiplabel";
FLabel->Text = this->ToString();
if (FLabel->Canvas != NULL) {
Height = FLabel->Canvas->TextHeight(FLabel->Text);
}
FLabel->Align = TAlignLayout::Client;
FLabel->TextAlign = TTextAlign::Center;
FLabel->VertTextAlign = TTextAlign::Center;
FTimer = new TTimer(Owner);
FTimer->OnTimer = OnTimer;
FTimer->Enabled = true;
FTimer->Interval = 500;
FActiveControl = NULL;
FCounter = 1000;
FBorderWidth = 10;
}
//---------------------------------------------------------------------------
__fastcall TToolTipPanel::~TToolTipPanel() {
}
- 8. Fügen Sie eine public-Methode hinzu, um den Kurzhinweis an der angegebenen Position anzuzeigen:
- Delphi:
public
procedure ShowToolTip(AX, AY: Single);
implementation
procedure TToolTipPanel.ShowToolTip(AX, AY: Single);
begin
Position.Point := PointF(AX,AY); //sets the tooltip position to the specified point
//calculates the size of the tooltip depending on the text to be displayed
Height := FLabel.Canvas.TextHeight(FLabel.Text) + 2 * FBorderWidth;
Width := FLabel.Canvas.TextWidth(FLabel.Text) + 2 * FBorderWidth;
//sets the tooltip as visible
Visible := True;
end;
- C++:
- Fügen Sie in der Header-Datei (.h-Datei) der Klasse TToolTipPanel den folgenden Code hinzu:
public:
__fastcall void ShowToolTip(float AX, float AY);
-
- Fügen Sie in der CPP-Datei der Klasse TToolTipPanel den folgenden Code hinzu:
void __fastcall TToolTipPanel::ShowToolTip(float AX, float AY){
Position->Point = PointF(AX,AY);
Height = FLabel->Canvas->TextHeight(FLabel->Text)+ 2 * FBorderWidth;
Width = FLabel->Canvas->TextWidth(FLabel->Text) + 2 * FBorderWidth;
Visible = True;
}
- 9. Ein Kurzhinweis wird typischerweise für die aktuelle Position des Cursors angezeigt. Ein Kurzhinweis zeigt auch Text an, der Informationen über die aktuelle Position enthält.
- In diesem Fall zeigt der Kurzhinweis den folgenden Text an:
- "ToolTip for component: "
- und den Namen der Komponente, auf der sich der Mauszeiger befindet.
- Wird keine Komponente gefunden, wird Folgendes angezeigt:
- "ToolTip for mouse pos "
- und die Koordinaten des Mauszeigers.
- Wenn der Kurzhinweis nur für Eingabesteuerelemente definiert ist, wird dieser Text angezeigt:
- "ToolTip for "
- und der Name des Eingabesteuerelements mit dem Fokus. Der Kurzhinweis wird unter dem Eingabesteuerelement angezeigt, damit das Steuerelement nicht verdeckt wird und der Benutzer den Text eingeben kann.
- Der angezeigte Text kann natürlich entsprechend Ihren Wünschen geändert werden.
Die OnTimer-Implementierung sollte wie folgt vorgenommen werden:
- Delphi:
procedure TToolTipPanel.OnTimer;
var
LActiveControl : IControl;
LControl : TControl;
LMousePos : TPointF;
LObject : IControl ;
begin
//test to detect for which kind of controls to display the control
if not FOnlyInputFields then
begin
// tests if the FMousePoint is actualized
if Screen.MousePos <> FMousePoint then
begin
FMousePoint := Screen.MousePos ;
FCounter := 0;
Visible := False;
end ;
Inc(FCounter);
case FCounter of
0..2: Visible := False ;//simulates a delay on displaying the tooltip
3:
begin
Text := '';
if Parent is TForm then
begin
//identifies the object on which the mouse cursor is located
LObject := (Parent as TForm).ObjectAtPoint(FMousePoint) ;
if Assigned(LObject) then
Text := LObject.GetObject.Name;
end;
//if no object is found, the tooltip displays the mouse cursor coordinates
if Text = '' then
Text := 'ToolTip for mouse pos ' + PointToString(FMousePoint)
else
Text := 'ToolTip for component: ' + Text ;
LMousePos := (Parent as TForm).ScreenToClient(FMousePoint);
//displays the tooltip
ShowToolTip(LMousePos.X, LMousePos.Y);
end;
// the tooltip is displayed for a limited time. In this case it is displayed until FCounter reaches 10
4..10:;
else
FCounter := 1000;
Visible := False ;
end;
end
else
begin
//identifies the active control (the control in focus)
if Parent is TForm then
LActiveControl := (Parent as TForm).Focused;
// checks if the object in focus is an input control (and a TEdit or a TEdit descendant)
if Assigned(LActiveControl) and (LActiveControl.GetObject <> FActiveControl) then
begin
Visible := False ;
FActiveControl := LActiveControl.GetObject;
if (FActiveControl is TEdit) then
FCounter := 0;
end;
Inc(FCounter);
case FCounter of
0..2: Visible := False ;//simulates a delay on displaying the tooltip
3..10: // the tooltip is displayed for the FActiveControl control, if it exists, under the input control,
// so the tooltip doesn't cover the input area
begin
if assigned(LActiveControl) then
begin
LControl := (LActiveControl as TControl);
Text := 'ToolTip for ' + LControl.Name ;
ShowToolTip(LControl.Position.X + 20, LControl.Position.Y + LControl.Height);
end;
end
else
FCounter := 1000;
Visible := False ;
end;
end;
end;
- C++:
- Fügen Sie in der Header-Datei (.h-Datei) der Klasse TToolTipPanel den folgenden Code hinzu:
void __fastcall TToolTipPanel::OnTimer(TObject* Sender) {
IControl *LActiveControl;
TControl *LControl;
TPointF LMousePos;
IControl *LObject;
if (!FOnlyInputFields) {
if (Screen->MousePos() != FMousePoint) {
FMousePoint = Screen->MousePos();
FCounter = 0;
Visible = False;
}
FCounter++;
switch (FCounter) {
case 0:
case 1:
case 2:
Visible = False;
break;
case 3:
Text = "";
if ((dynamic_cast<TForm*>(Parent)) != NULL) {
TForm& ref_object = dynamic_cast<TForm&>(*Parent);
LObject = ref_object.ObjectAtPoint(FMousePoint);
if (LObject != NULL) {
Text = LObject->GetObjectW()->Name;
}
}
if (Text == "") {
Text = "ToolTip for mouse pos " + PointToString(FMousePoint);
}
else {
Text = "ToolTip for component: " + Text;
}
LMousePos = dynamic_cast<TForm*>(Parent)->ScreenToClient(FMousePoint);
ShowToolTip(LMousePos.X, LMousePos.Y);
break;
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
break;
default:
FCounter = 1000;
Visible = False; ;
}
}
else {
if ((dynamic_cast<TForm*>(Parent)) != NULL) {
TForm& ref_LObject = dynamic_cast<TForm&>(*Parent);
LActiveControl = ref_LObject.Focused;
if ((LActiveControl != NULL) & (LActiveControl->GetObjectW()!= FActiveControl)) {
Visible = False;
FActiveControl = LActiveControl->GetObjectW();
if ((dynamic_cast<TEdit*>(FActiveControl)) != NULL) {
FCounter = 0;
}
}
FCounter++;
switch (FCounter) {
case 0:
case 1:
case 2:
Visible = False;
break;
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
if (LActiveControl != NULL) {
LControl = System::interface_cast<TControl, IControl>(LActiveControl);
Text = "ToolTip for " + LControl->Name;
ShowToolTip(LControl->Position->X + 20, LControl->Position->Y + LControl->Height);
}
break;
default:
FCounter = 1000;
Visible = False; ;
}
}
}
}
- 10. Das endgültige Interface von TToolTipPanel sollte folgendermaßen aussehen:
- Delphi:
type
TToolTipPanel = class(TPanel)
private
FOnlyInputFields: Boolean;
FMousePoint: TPointF;
FCounter: Cardinal;
FActiveControl: TFmxObject;
FLabel: TLabel;
FTimer: TTimer;
FBorderWidth: Single;
function GetToolTipText: string;
procedure SetToolTipText(const Value: string);
procedure OnTimer(Sender: TObject);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure ShowToolTip(AX, AY: Single);
property Text: string read GetToolTipText write SetToolTipText;
property BorderWidth: Single read FBorderWidth write FBorderWidth;
property OnlyInputFields: Boolean read FOnlyInputFields
write FOnlyInputFields;
end;
- C++:
class TToolTipPanel : public TPanel{
private:
TLabel *FLabel;
TPointF FMousePoint;
TFmxObject *FActiveControl;
TTimer *FTimer;
unsigned FCounter;
bool FOnlyInputFields;
float FBorderWidth;
UnicodeString _fastcall GetToolTipText();
void _fastcall SetToolTipText (const UnicodeString Value);
void _fastcall OnTimer (TObject *Sender);
public:
__fastcall TToolTipPanel(TComponent* Owner);
__fastcall virtual ~TToolTipPanel(void);
__fastcall void ShowToolTip(float AX, float AY);
__published:
__property UnicodeString Text = {read = GetToolTipText, write = SetToolTipText};
__property bool OnlyInputFields = {read = FOnlyInputFields, write = FOnlyInputFields };
__property float BorderWidth = {read = FBorderWidth, write = FBorderWidth };
};
Verwenden des Kurzhinweises
- 1. Fügen Sie im Formular-Designer Ihre Komponenten hinzu, zum Beispiel: eine TButton-Komponente, eine TCheckBox-Komponente, eine TEdit-Komponente, eine TMemo-Komponente, eine TRectangle-Komponente.
- 2. Fügen Sie in die Unit-Deklaration des Formulars die oben definierte Unit ToolTip ein.
- 3. Fügen Sie dem Formular einen private-Member mit dem Typ TToolTipPanel hinzu.
-
- Delphi:
private
TT : TToolTipPanel;
-
- C++:
- Fügen Sie in der Header-Datei (.h-Datei) der private-Deklaration von TForm den folgenden Code hinzu:
- C++:
private: // User declarations
TToolTipPanel *TT;
- 4. Erstellen Sie im Ereignis OnCreate des Formulars ein TToolTipPanel.
-
- Delphi:
procedure TForm1.FormCreate(Sender: TObject);
begin
TT := TToolTipPanel.Create(Form1);
TT.Parent := Self ;
end;
-
- C++:
__fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner){
TT = new TToolTipPanel(this);
TT->Parent = this;
}
- 5. Um das Verhalten des Kurzhinweises für die Werte True oder False der Eigenschaft OnlyInputFields zu testen, fügen Sie Folgendes in das Ereignis OnChange des Steuerelements TCheckBox ein:
-
- Delphi:
procedure TForm1.CheckBox1Change(Sender: TObject);
begin
TT.OnlyInputFields := CheckBox1.IsChecked;
end;
-
- C++:
void __fastcall TForm1::CheckBox1Change(TObject *Sender){
TT->OnlyInputFields = CheckBox1->IsChecked;
}
- 6. Führen Sie die Anwendung aus.
- Die folgenden Abbildungen zeigen den erstellten Kurzhinweis:
-
- Die nächste Abbildung zeigt die Auswirkung eines Kurzhinweises für eine Eingabekomponente mit der auf True gesetzten Eigenschaft OnlyInputFields: