Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Überschreiben einer geerbten Eigenschaft


Peter18 - Sa 27.02.16 19:00
Titel: Überschreiben einer geerbten Eigenschaft
Ein freundliches Hallo an alle,

ich habe eine Komponente von TPanel abgeleitet. Da ich Caption von TPanel nicht verwenden möchte habe ich ein TLabel positioniert und möchte nur das als Caption verwenden.
Im Objektinspektor wird anscheinend Caption von TPanel verwendet. Meine Frage: Wie erreiche ich, dass die neue Deklaration von Caption im Objektinspektor verwendet wird? Die Hilfe war in dieser Hinsicht nicht sehr Aussagekräftig.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
type
  T_LoadCont = class(TPanel)
  private
    { Private-Deklarationen }
    oPnl     : TPanel      ;   // Panel auf dem die Fortschrittsanzeige sitzt
    oProgBar : TProgressBar;   // Balkenanzeige
    oLbl     : TLabel      ;   // Beschreibung der Aktion

    // Properties
    procedure WriteMin ( M : Integer );
    procedure WriteMax ( M : Integer );
    procedure WritePos ( P : Integer );
    procedure WriteStep( S : Integer );
    procedure WriteCap ( C : String  );

  protected
    { Protected-Deklarationen }

  public
    { Public-Deklarationen}
    constructor Create( Owner: TComponent );                           override;

    // Methoden
    procedure SetLd  ( Min, Max : Integer; Capt : String; Vis : Boolean );
    procedure SetRang( Min, Max : Integer                               );
    procedure SetStep(                     Capt : String                );
    procedure StepIt;

    // Eigenschaften
    property Min      : Integer               Write WriteMin ;
    property Max      : Integer               Write WriteMax ;
    property Position : Integer               Write WritePos ;
    property Step     : Integer               Write WriteStep;
    property Caption  : String                Write WriteCap ;


Grüße von der Nordsee

Peter


jaenicke - So 28.02.16 00:12

Ich frage mich wieso du dafür ein Label benutzt? Ein Label ist dafür da, dass du einen Text als Komponente auf ein Formular legen kannst. Aber wenn du sowieso eine eigene Komponente hast, kannst du den Text doch einfach selbst dort ausgeben.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
  protected
    procedure WmPaint(var Message: TMessage); message WM_PAINT;
//...

procedure T_LoadCont.WmPaint(var Message: TMessage);
begin
  inherited;
  Canvas.TextOut(1010, Caption);
end;
Schriftart, -farbe, -hintergrund usw. musst du natürlich entsprechend setzen.

Damit die Originalcaption nicht ausgegeben wird, kannst du einfach ShowCaption auf False setzen.

Ansonsten könntest du WM_SETTEXT oder CM_TEXTCHANGED abfangen und dort auf das Setzen des Textes reagieren. Im Falle von WM_SETTEXT kannst du auch das inherited weglassen um zu verhindern, dass die Caption weiter verarbeitet wird, kannst sie also dann selbst speichern ohne dass sie angezeigt wird.

Die Eigenschaft selbst umzuleiten, geht nicht gut, weil man an die Originalproperty immer noch herankommt. Oberflächlich (so dass es über den Objektinspektor gehen sollte) funktioniert es aber schon, aber du musst deine Propertys dann auch unter published aufführen.

// EDIT:
Ok, ShowCaption gibt es erst ab Delphi 2009...
Dann musst du WM_SETTEXT abfangen und selbst behandeln.


Peter18 - So 28.02.16 12:28

Hallo Sebastian,

Dank Dir für die Antwort. Deine Frage ist leicht zu beantworten. Ich habe ein einfaches kleines Delphi 4. Die Hilfe und ein paar PDF-Dateien sind die einzige Informationsquelle. Wenn ich das falsche Stichwort wähle, erhalte ich nicht die Antworten, die ich suche. "WM_SETTEXT" taucht da nirgens auf, "Canvas.TextOut" kann ich schon finden, wenn ich danach suche, suche ich denn? Daher bin ich für jeden Tipp dankbar. Alles, was ich über Delphi weiß habe ich aus der Hilfe, dem "Entwicklerhandbuch" und diesem Forum, wobei das Forum eine sehr große Hilfe war und ist.

Doch mir ist noch nicht klar, wie ich verhindern kann, dass Caption vom Panel vom Objektinspektor verwendet wird. Zur Laufzeit sieht es aus wie gewollt. Ist es vielleicht der beste Weg statt "T_LoadCont = class(TPanel)" "T_LoadCont = class" zu verwenden? oder wie kann ich Caption von TPanel auf meine Property umleiten?


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
    property Caption  : String                Write WriteCap ;
.
.
.
procedure T_LoadCont.WriteCap( C : String );
begin
  inherited Caption := '';
  oLbl.Caption      := C ;
end;


Grüße von der wieder sonnigen Nordsee

Peter


jaenicke - So 28.02.16 22:20

user profile iconPeter18 hat folgendes geschrieben Zum zitierten Posting springen:
Ich habe ein einfaches kleines Delphi 4. Die Hilfe und ein paar PDF-Dateien sind die einzige Informationsquelle.
Viel wichtiger wäre der Quelltext der Delphi Units als Referenz. Ohne den könnte ich kaum sinnvoll eigene Komponenten entwickeln.
Aber das Thema Turbo Delphi hatten wir ja glaube ich schon...

Ich sehe jedenfalls bei Delphi 4 keine Möglichkeit die Ausgabe der Originalcaption zu unterdrücken, da dies fest beim Zeichnen in Paint passiert. Damit bleiben dir zwei Möglichkeiten:


Peter18 - Mo 29.02.16 11:12

Hallo Sebastian,

nochmals Dank. In der Tat, es wäre schön, wenn ich die Quellen hätte. Dann hätte ich mir sicher auch schon einiges davon abgucken können.

Ist "T_LoadCont = class" statt "T_LoadCont = class(TPanel)" keine Möglichkeit? Wenn ich eine neue Klasse definiere und darin dann ein Panel erzeuge, statt das ganze von TPanel abzuleiten?

Grüße von der kalten Nordsee

Peter


jaenicke - Mo 29.02.16 17:10

Wenn du eine neue Klasse ableitest, hast du die Eigenschaften von TPanel gar nicht mehr. Dann ist doch eine einfache neue Property wie ich schon vorgeschlagen habe viel einfacher.


Peter18 - Mo 29.02.16 19:53

Hallo Sebastian,

es scheint mir einfacher, weil ich TPanel nur als Ablagefläche für ein paar Objekte brauche, die ich dann über Panel unsichtbar machen kann. In meinem constructor wird Caption bereits leer gesetzt, dennoch erscheint Caption des Panel zur Entwicklungszeit. Zur Laufzeit ist aber alles wie es sein soll. Ist also nur ein Schönheitsfehler, aber wenn möglich möchte ich es sauber programmieren (und dazu lernen!).

Ich werde es mal ausprobieren und berichten. Falls aber Jemand einen Tipp hat ist er wilkommen.

Grüße von der Nordsee

Peter


jaenicke - Mo 29.02.16 20:36

Da kommen wir der Sache schon näher...
Das passiert, wenn man nach einer Lösung fragt statt das eigentliche Problem zu nennen. ;)

Du willst also eigentlich nur die Caption verstecken?

Dann überschreibe einfach Loaded. Das wird aufgerufen nachdem die Eigenschaften aus dem Objektinspektor gesetzt sind. Dort kannst du Caption leer machen.

Delphi-Quelltext
1:
2:
  protected
    procedure Loaded; override;


doublecross - Di 01.03.16 10:37

Hallo,

meines Wissens kannst du published Propertys nicht in eine niedrigere Sichtbarkeitsstufe verschieben. Das wäre aber nötig, damit es nicht im Objektinspektor erscheint.

Wahrscheinlich kannst du das Problem aber umgehen indem du nicht TPanel sondern TCustomPanel beerbst. Dort sind viel der Eigenschaften, die bei TPanel published sind noch protected und somit nicht sichtbar. Du musst dann lediglich die Propertys die du im Objektinspektor sehen willst im published Bereich deiner Klasse redefinieren.


Peter18 - Do 03.03.16 13:39

Hallo doublecross,

Dank Dir für Deine Antwort. Ich habe nun einen anderen Weg probiert, und bin auf neue Probleme gestoßen.

Nun leite ich von TComponent ab und habe das Hauptpanel selbst erzeugt. Da ich es nur als Oberfläche brauche sind die anderen Eigenschaften nicht so wichtig.

Nun aber habe ich mein (altes) Objekt aus der Delphi-Objektpalette entfernt und wie folgt deklariert:


Delphi-Quelltext
1:
2:
type
  T_LoadCont = class(TComponent)                 //(TPanel)


Statt es neu compiliert in der Palette anzuzeigen, erscheint es jedoch nicht. Er behauptet es zwar, doch das Logo erscheint nicht. Kann es sein, dass irgendwo noch Reste von der alten Komponente vorhanden sind, die einen neuen Eintrag verhindern?

Grüße von der Nordsee

Peter


Peter18 - Sa 05.03.16 15:11

Ein freundliches Hallo an alle,

und wieder in eine Falle getappt!

Jetzt erscheint das Symbol aus der Galerie (wie beim Timer) und das Objekt auf dem Formular. Ich hoffe jemand kann mir das erklären.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
type
  T_LoadCont = class(TComponent)                 //(TPanel)
  private
    { Private-Deklarationen }
    oMnPnl   : TPanel      ;   // HauptPanel auf dem alle Komponenten sitzen
    oPnl     : TPanel      ;   // Panel auf dem die Fortschrittsanzeige sitzt
    oProgBar : TProgressBar;   // Balkenanzeige
    oLbl     : TLabel      ;   // Beschreibung der Aktion

    // Properties
    procedure WriteCap    ( C : String  );
    procedure WriteTop    ( M : Integer );
    procedure WriteLeft   ( M : Integer );
    procedure WriteHeight ( M : Integer );
    procedure WriteWidth  ( M : Integer );
    procedure WriteMin    ( M : Integer );
    procedure WriteMax    ( M : Integer );
    procedure WritePos    ( P : Integer );
    procedure WriteStep   ( S : Integer );
    procedure WriteVisible( B : Boolean );

  protected
    { Protected-Deklarationen }

  public
    { Public-Deklarationen}
    constructor Create( Owner: TComponent );                           override;
    destructor  Destroy;                                               override;

    // Methoden
    procedure SetLd  ( Min, Max : Integer; Capt : String; Vis : Boolean );
    procedure SetRang( Min, Max : Integer                               );
    procedure SetStep(                     Capt : String                );
    procedure StepIt;

    // Eigenschaften
    property Top      : Integer               Write WriteTop    ;
    property Left     : Integer               Write WriteLeft   ;
    property Height   : Integer               Write WriteHeight ;
    property Width    : Integer               Write WriteWidth  ;
    property Min      : Integer               Write WriteMin    ;
    property Max      : Integer               Write WriteMax    ;
    property Position : Integer               Write WritePos    ;
    property Step     : Integer               Write WriteStep   ;
    property Visible  : Boolean               Write WriteVisible;

  published
    { Published-Deklarationen }
    property Caption  : String                Write WriteCap    ;

  end;

procedure Register;

implementation

{$R *.res}


Verwende ich "class(TGraphicControl)" so ist das nicht der Fall. Wie wird das gesteuert? "TGraphicControl" ist doch ein Abkömling von "TComponent".

Grüße von der Nordsee

Peter


jaenicke - Sa 05.03.16 16:33

Du meinst bei TGraphicControl erscheint das Symbol nicht in der Komponentenpalette?
Das ist bei mir nicht so.

Oder meinst du auf dem Formular? TGraphicControl ist auch keine nonvisuelle Komponente, da siehst du die Komponente selbst.


Peter18 - Sa 05.03.16 16:54

Hallo Sebastian,

Das Symbol erscheint immer in der Komponentenpalette. Wenn ich "TComponent" verwende erscheint das Symbol auf dem Formular (und das Objekt), mit "TGraphicControl" erscheint nur das Objekt auf dem Formular.

Grüße von der Nordsee

Peter


jaenicke - Sa 05.03.16 18:06

Wie gesagt, TGraphicControl ist keine nonvisuelle Komponente. Deshalb siehst du da die Komponente wie sie programmiert ist. Nur nonvisuelle Komponenten werden (weil sie keine eigene Darstellung haben) mit dem kleinen Quadrat plus Symbol als Platzhalter dargestellt.


Peter18 - Sa 05.03.16 18:52

Hallo Sebastian,

doch wie wird das gesteuert??? Schließlich ist "TGraphicControl" doch ein Abkömling von "TComponent".

Grüße von der Nordsee

Peter


jaenicke - Sa 05.03.16 19:50

Das ist fest in der Delphi IDE so eingebaut und soweit ich weiß nicht änderbar. Warum auch?


Peter18 - So 06.03.16 18:54

Hallo Sebastian,

Dank Dir. Habe neue Probleme, aber die passen nicht mehr ganz hier rein. Mache eine neue Frage auf.

Grüße von der sonnigen Nordsee

Peter