Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Hint überschreiben (https://www.delphipraxis.net/153446-hint-ueberschreiben.html)

Rainer Wolff 3. Aug 2010 10:19

Delphi-Version: 2006

Hint überschreiben
 
Hallo,

ich würde gerne bei einigen eigenen Komponenten die Eigenschaft Hint so überschreiben, dass ich zur Entwurfszeit einen Hint setze, der aber zur Laufzeit mit zusätzlichen Angaben ergänzt wird.

Hint ist ja in TWincontrol so definiert:
Delphi-Quellcode:
  property Hint: string read FHint write FHint;
Ich hätte nun gern sowas:
Delphi-Quellcode:
TMyComponent = class(TWinControl)
published
  property Hint: string read GetHint;
end;

TMyComponet.GetHint: string;
begin
  result:=FHint+' Mein zusätzlicher Text';
end;
Das Überschreiben grundsätzlich geht ja, wenn ich im Quelltext den Hint abfrage, erhalte ich auch den erweiterten Text, allerdings wird zur Laufzeit nur der Grundtext als Hint angezeigt.

Kann ich dies auf Komponentenebene lösen, oder bleibt hier nur der Umweg über eine ApplicationEvents-Komponente, in der ich den Hint entsprechend modifiziere?

blackfin 3. Aug 2010 10:54

AW: Hint überschreiben
 
Du willst also im IDE-Editor den Hint ohne den Zusatz-Text haben, zur Laufzeit aber mit?
Dann ist ComponentState dein Freund :)

Hier ein Beispiel mit einer TEdit-Ableitung:

Delphi-Quellcode:
unit my_hintedit;

interface

uses
  Classes,StdCtrls
;

type
  TmyHintEdit = class(TEdit)
    private
      FHint: string ;
      function GetHint(): string ;
    public
      constructor Create(AOwner: TComponent) ; override ;
    published
      property Hint read GetHint write FHint ;
  end;

procedure Register;

implementation

// Constructor
constructor TmyHintEdit.Create(AOwner: TComponent);
begin
   inherited Create(AOwner);
end;

// Get hint (without additional Text in IDE, with additional text at runtime)
function TmyHintEdit.GetHint(): string;
begin
   // in IDE
   if (csDesigning in ComponentState) then
    Result := FHint
    // at runtime
   else        
    Result := FHint + ' <Zusatz-Text>' ;
end;

// Register the new control in a toolbar
procedure Register;
begin
   RegisterComponents('My Controls', [TmyHintEdit]);
end;

end.
Natürlich würd ich an deiner Stelle den Zusatz-Text auch noch dynamisch setzen, aber das ist ja ein Kinderspiel :)

Rainer Wolff 3. Aug 2010 12:12

AW: Hint überschreiben
 
Ausprobiert hab ichs, aber tun tuts nicht.

Wenn ich den Hint direkt auslese(z.b. Form.Caption:=MyEdit.Hint), wird er, wie in meinem Beispiel auch, richtig zugewiesen. Wenn ich mit der Maus über das Edit fahre, sehe ich jedoch nichts.
Ich denke, da auch hier nichts mit overload deklariert wird, greift die VCL auf alle Components als TWinControl zu (cast) und dadurch wird der Hint der Basisklasse im Hintfenster angezeigt, der ja aber im Beispiel nicht gesetzt wird, da in der vererbten Klasse ein neuer Hint definiert wird.

DeddyH 3. Aug 2010 12:19

AW: Hint überschreiben
 
Eine dumme Frage: ShowHint hast Du aber auf true gesetzt, oder?

blackfin 3. Aug 2010 12:25

AW: Hint überschreiben
 
Ah, stimmt...er hat recht.
Das Mouseover funktioniert nicht mehr, sobald man Hint überschreibt.
Wenn man im Constructor die Property mit inherited überschreibt, gehts auch nicht.
Mal überlegen....

DeddyH 3. Aug 2010 12:57

AW: Hint überschreiben
 
Funktioniert es so?
Delphi-Quellcode:
type
  TmyHintEdit = class(TEdit)
  private
    function GetHint: string;
    procedure SetHint(const value: string);
  published
    property Hint: string read GetHint write SetHint;
  end;

...

function TmyHintEdit.GetHint: string;
begin
  Result := inherited Hint;
end;

procedure TmyHintEdit.SetHint(const value: string);
begin
  if not (csDesigning in ComponentState) then
    inherited Hint := value + ' Test'
  else
    inherited Hint := value;
end;

MarcoWarm 3. Aug 2010 13:15

AW: Hint überschreiben
 
Wie ich die VCL kenne wird sicherlich innerhalb der Klasse auf den Hint nur über die private FHint-Variable verwiesen.

blackfin 3. Aug 2010 14:00

AW: Hint überschreiben
 
Jup, sieht ganz so aus :wall::wall:

guinnes 3. Aug 2010 14:12

AW: Hint überschreiben
 
Beim MouseEnter Alten Hint merken, ergänzen
Beim MouseLeave Alten Hint zurückschreiben
Oder, wenn du z.B. beim überfahren der Items einer Listbox die Caption des Items als Hint haben möchtest :
Delphi-Quellcode:
procedure TForm1.ListBoxMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  item : integer;
  HS  : string;
  LB  : TListBox;
begin
  LB := Sender as TListbox;
  item := LB.itemAtpos(Point(x, y), true);
  if item >= 0 then
  begin
    HS := LB.Items.Strings[Item];
    if HS <> LB.Hint then
    begin
      LB.Hint := HS;
      Application.ActivateHint(Point(x, y));
    end;
  end;
end;
Lässt sich sicherlich auch auf andere Controls ausweiten ohne eine neue Klasse abzuleiten

Rainer Wolff 3. Aug 2010 18:12

AW: Hint überschreiben
 
Zitat:

Zitat von guinnes (Beitrag 1039249)
Beim MouseEnter Alten Hint merken, ergänzen
Beim MouseLeave Alten Hint zurückschreiben

Das wars nun gar nicht, was ich wollte.
Inzwischen hab ich meinen Code in den Komponenten noch etwas hin und her geschoben und mache es so: Alle Komponenten, für die ich das ganze brauche (Abgeleitet von Shape, Label, Bitmap, Edit...) haben sowieso ein gemeinsames Interface.

Ich verwende ein TApplicationEvents-Objekt und in OnShowHint:
Delphi-Quellcode:
procedure TMainWindow.ApplicationEvents1ShowHint(var HintStr: string;
  var CanShow: Boolean; var HintInfo: THintInfo);
begin
  if Supports(HintInfo.HintControl, IMyInterface) then
  begin
    HintStr:=Hintstr+' '+(HintInfo.HintControl as IMyInterface).myZusatzHint;
  end;
end;
Aber ich wollte das ganze halt am liebsten in die Komponenten rein schieben, damit ich nicht in jedem Projekt im Hauptformular an den zitierten Code denken muss.
Da vermute ich jetzt einfach, dass es mit dem Hint überschreiben nicht geht, wenn nicht noch jemand eine geniale Idee hat.

Gruß Rainer

himitsu 3. Aug 2010 18:25

AW: Hint überschreiben
 
Wieso muß man eigentlich einen eigenen Hint-Property erstellen?

Die VCL kennt nur "ihr" Property und nutzt auch dieses für die Anzeige.
Was sie nicht kennt, das kann die VCL nicht nutzen.

Uwe Raabe 3. Aug 2010 18:59

AW: Hint überschreiben
 
Zitat:

Zitat von himitsu (Beitrag 1039310)
Wieso muß man eigentlich einen eigenen Hint-Property erstellen?

Die VCL kennt nur "ihr" Property und nutzt auch dieses für die Anzeige.
Was sie nicht kennt, das kann die VCL nicht nutzen.

Genau deswegen funktiionieren die ganzen Ansätze mit dem Überschreiben des Properties ja nicht. Man hätte nur dann Erfolg, wenn es virtuelle Getter und Setter gäbe, aber die gibt es nun mal nicht...

Rainer Wolff 3. Aug 2010 19:11

AW: Hint überschreiben
 
Zitat:

Zitat von himitsu (Beitrag 1039310)
Wieso muß man eigentlich einen eigenen Hint-Property erstellen?

Zum Hintergrund des ganzen: Die Komponenten benutze ich zur Visualisierung von Maschinensteuerungen. Also z. B. Endschalter oder Positionsanzeige. Die Komponenten haben eine Bedeutung, die im Hint auch angezeigt wird, also z. B. Türe offen/geschlossen, oder aktuelle Antriebsposition.
Ausserdem haben die Komponenten noch Eigenschaften, die sie mit der Steuerung verknüpfen, welches Eingangsbit, oder Merkerbit z.b. mit der Komponente angesprochen wird.
Diese Info möchte ich zusätzlich zur eigentlichen Komponentenbedeutung im Hint anzeigen, also z. B. "Kontrollschalter Türe (Eingang 8.0)", aber nicht grundsätzlich, sondern wählbar.

Gruß Rainer

himitsu 3. Aug 2010 20:37

AW: Hint überschreiben
 
Entweder du mußt ständig/regelmäßig alle Hint-Texte anpassen, also vorsorglich bevor sie angezeigt werden könnten, oder ...


entweder man definiert einen Marker, welcher dann ersetzt wird:
Delphi-Quellcode:
Label1.Hint := ':MyHint:'; // natürlich im OI deklariert
Label1.ShowHint := True;

procedure TForm5.FormCreate(Sender: TObject);
begin
  Application.OnShowHint := ShowHint;
end;

procedure TForm5.ShowHint(var HintStr: string; var CanShow: Boolean; var HintInfo: Controls.THintInfo);
begin
  if HintStr = ':MyHint:' then
    HintStr := 'die aktuelle Zeit ist ' + TimeToStr(Now);
  if HintStr = ':MyOtherHint:' then
    HintStr := 'das aktuelle Datum ist ' + DateToStr(Now);
end;
das geht auch mit Teilen
Delphi-Quellcode:
Label1.Hint := 'die aktuelle Zeit ist :MyHint:';
Label1.ShowHint := True;

procedure TForm5.FormCreate(Sender: TObject);
begin
  Application.OnShowHint := ShowHint;
end;

procedure TForm5.ShowHint(var HintStr: string; var CanShow: Boolean; var HintInfo: Controls.THintInfo);
begin
  HintStr := StringReplace(HintStr, ':MyHint:', TimeToStr(Now), []);
  HintStr := StringReplace(HintStr, ':MyOtherHint:', DateToStr(Now), []);
end;
man kann aber auch über's Control gehn:
Delphi-Quellcode:
procedure TForm5.FormCreate(Sender: TObject);
begin
  Application.OnShowHint := ShowHint;
end;

procedure TForm5.ShowHint(var HintStr: string; var CanShow: Boolean; var HintInfo: Controls.THintInfo);
begin
  if HintInfo.HintControl = Label1 then
    HintStr := 'die aktuelle Zeit ist ' + TimeToStr(Now);
end;
ShowHint wird immer aufgerufen, kurz bevor irgendein Hint angezeigt wird.


Aber schöner wäre es natürlich, wenn in jeder Komponente auch ein OnHint existieren würde, damit man vor Ort reagieren und sich dort entsprechende Eventhandler schreiben könnte.

Gut, man könnte auch ein anderes Event mißbrauchen, welches man sonst nirgends in der Anwendung verwendet hat.
> OnEndDock bietet sich oftmals an
Delphi-Quellcode:
Label1.ShowHint := True;
Label1.OnEndDock := Label1EndDock;

procedure TForm5.FormCreate(Sender: TObject);
begin
  Application.OnShowHint := ShowHint;
end;

procedure TForm5.ShowHint(var HintStr: string; var CanShow: Boolean; var HintInfo: Controls.THintInfo);
begin
  if Assigned(TForm(HintInfo.HintControl).OnEndDock) then
  begin
    TForm(HintInfo.HintControl).OnEndDock(HintInfo.HintControl, nil, 0, 0);
    HintStr := TForm(HintInfo.HintControl).Hint;
  end; // TForm wurde nur verwendet, da .Hint und
end; // .OnEndDock in TControl als protected deklariert sind

procedure TForm5.Label1EndDock(Sender, Target: TObject; X, Y: Integer);
begin
  TLabel(Sender).Hint := 'die aktuelle Zeit ist ' + TimeToStr(Now);
  // oder Label1.Hint := 'die aktuelle Zeit ist ' + TimeToStr(Now);
end;

Uwe Raabe 3. Aug 2010 22:41

AW: Hint überschreiben
 
Zitat:

Zitat von Rainer Wolff (Beitrag 1039316)
Zum Hintergrund des ganzen: Die Komponenten benutze ich zur Visualisierung von Maschinensteuerungen. Also z. B. Endschalter oder Positionsanzeige. Die Komponenten haben eine Bedeutung, die im Hint auch angezeigt wird, also z. B. Türe offen/geschlossen, oder aktuelle Antriebsposition.
Ausserdem haben die Komponenten noch Eigenschaften, die sie mit der Steuerung verknüpfen, welches Eingangsbit, oder Merkerbit z.b. mit der Komponente angesprochen wird.
Diese Info möchte ich zusätzlich zur eigentlichen Komponentenbedeutung im Hint anzeigen, also z. B. "Kontrollschalter Türe (Eingang 8.0)", aber nicht grundsätzlich, sondern wählbar.

Wie wäre es, wenn du in einem OpUpdate-Event einer Action, im Application.OnIdle oder in einem Timer.OnTrigger die Hints alle zentral anpasst. Dann hast du wenigstens alles an einer Stelle. Macht natürlich nur Sinn, wenn sich der Hint-Inhalt hireichend oft ändert.

himitsu 4. Aug 2010 07:37

AW: Hint überschreiben
 
Klar könnte man im Prinzip alle Hints sofort anpassen, wo sich der Status ändert.
Also entweder bekommt man die Änderung mit und ändert da auch den Hint
oder man pollt eben über 'nen Timer o.Ä. und fragt ständig alle Status (mit langem U oder halt Statusse :stupid:) abund setzt die Hints neu.

Auch wenn die meisten der jedesmal gesetzten Hints wohl niemals angezeigt wird. (also könnte man das Ganze uch wieder als Pollen bezeichnen, was aus irgendwelchen unerfindlichen Gründen einige/viele nicht mögen :roll: )

Oder man reagiert eben auf das Anzeigen eines Hints, fragt kurz den aktuellen Status ab und setzt nur diesen einen Hint.

Sherlock 4. Aug 2010 16:10

AW: Hint überschreiben
 
Mal ein anderer Lösungsansatz:
Hints sind in der Regel zweigeteilt. Es gibt den Shorthint und den LongHint. Untergebracht sind beide im Hinttext, getrennt durch das Pipe-Symbol. WEnn man jetzt zur Laufzeit etwas einfach an den Hint dranhängt, dann hängt man eigentlich etwas an den Longhint-Anteil an. Ich habe nicht den blassesten Dunst eines Schimmers einer ahnung, wo und wann zum Henker der Longhint eigentlich angezeigt werden soll. Ich hab ihn jedenfals noch nie gesehen.

Also muss der Hint zur Laufzeit von dem "|" befreit werden, dann sollte das IMHO auch klappen.

Sherlock
PS: Falls das alles Kokolores ist, bitte schnell wieder vergessen.
PPS: Die OH sagt zum LongHint, der könne im OnHint mit GetLongHint extrahiert werden...für eine weitere Verwendung.
S.


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