Ares hat folgendes geschrieben: |
Hallo!
Ich bastel gerade an einer eigenen Komponente für einen Dialog. Der Dialog verfügt über mehrere Buttons (OK, Abbrechen, etc.). Unter anderem soll es die Komponente erlauben, dass der Benutzer den Typ der Buttons frei wählen kann. Es soll also möglich sein TButton, TBitBtn, TSpeedButton oder irgendeine beliebige Komponente die von TWinControl abgeleitet ist als Button zu verwenden. Alle Buttons sollen dann vom ausgewählten Typ sein.
Wie kann ich sowas machen? Wie füge ich also eine Eigenschaft zu einer Komponente hinzu, die vom Typ "Typ" bzw. "Klasse" ist? Es müsste ja etwas sein wie:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| property ButtonType: "Typ" read FButtonType write SetButtonType; ... procedure MyComponent.SetButtonType(buttonType: "Typ"); begin if (buttonType is TWinControl) then FButtonType := "Typ" else raise Exception.Create('Button-Typ von TWinControl abgeleitet sein'); ... NextBtn := FButtonType.Create; end; ... |
Kann das funktionieren?
Vielen Dank für Ihre Hilfe
Ares |
Mit Bordmitteln sicher nicht. Typ oder Klasse kennt nur der Compiler, normalerweise geht das beim Compilieren unter und die exe enthält keine Informationen mehr darüber. Ausnahmen wie bei "is" oder "as" werden intern abgehandelt.
Die Felder eines Objekts sind Adressen (von Variablen oder Prozeduren) - ein Typ hat keine Adresse, eine Klasse auch nicht, zumindest solange es kein entsprechndes Objekt gibt.
Du kannst dir natürlich eine eigene Enumeration definieren (tInvalid,tInteger,tReal,...) und mit "is" arbeiten, ist aber recht umständlich. Ich verwende sowas für meine Ini-Dateien mit verschiedenen Konstruktoren:
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:
| TRKiniSettingRecord = record SetupControl : TControl; BackLink : TRKiniSettingValue; dirty : boolean; removed : boolean; FieldIndex : word; case TRKiniSettingVariant of sv_Undef : (vUndef : longint); sv_String : (VString : string[6]); sv_Bool : (vBool : boolean); sv_Integer : (vInteger : longint); sv_Real : (vReal : double); sv_Color : (vColor : TColor); sv_Pen : (vPen : longint); end;
constructor TRKiniSettingValue.Create_String (imax : integer; IG,II : TRKiniSettingName; Def : ShortString; EC : array of TEdit; OwnerTable : TRKIniSettingTable); var i : integer; begin sType := sv_String; for i := 0 to High (EC) do OwnerTable.SetupControlArray[i] := EC[i]; Create_General (imax,IG,II,Def,OwnerTable); end;
constructor TRKiniSettingValue.Create_Bool (imax : integer; IG,II : TRKiniSettingName; Def : Boolean; BC : array of TButtonControl; OwnerTable : TRKIniSettingTable); var i : integer; begin sType := sv_Bool; for i := 0 to High (BC) do OwnerTable.SetupControlArray[i] := BC[i]; Create_General (imax,IG,II,Def,OwnerTable); end;
constructor TBPMLogSettings.CreateTable (IC : TRKIniClass); begin inherited Create (IC); SetLength (SetupControlArray,70); with BLMainForm do begin Station_Node := TRKiniSettingValue.Create_Integer (-maxStationNo,'Station', 'Node',0, [nil] ,self); Station_Description := TRKiniSettingValue.Create_String (-maxStationNo,'Station', 'Description','', [nil] ,self); Station_CommPort := TRKiniSettingValue.Create_Integer (-maxStationNo,'Station', 'CommPortNumber',0, [nil] ,self); |
Ich lege dabei im Konstruktor der Settings-Klasse fest, welcher Typ, indem der entsprechende Konstruktor für den Eintrag aufgerufen wird.
Gruss Reinhard