Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Klassentyp zur Laufzeit ändern (https://www.delphipraxis.net/131456-klassentyp-zur-laufzeit-aendern.html)

Carsten1234 25. Mär 2009 06:16


Klassentyp zur Laufzeit ändern
 
Hallo zusammen,

ich habe eine MainForm vom Typ TForm, deren Klasse ich gerne in Abhängigkeit vom OS beim Programmstart ändern möchte.
Bsp.:
Delphi-Quellcode:
type
  TMainForm = class(TForm)
(...)
  end;

var
  MainForm: TMainForm;

(...)
  if (IsVista) then
<Pseudocode>
    MainForm:= TVistaForm;
</Pseudocode>
Geht das überhaupt?

Gruß, Carsten

Bernhard Geyer 25. Mär 2009 06:20

Re: Klassentyp zur Laufzeit ändern
 
So geht das nicht. Du könntest aber abhängig von OS die Instanz entsprechend erstellen:

Delphi-Quellcode:
if IsVista then
  Application.CreateForm(TVistaForm, frmMain)
else
  Application.CreateForm(TMainForm, frmMain);
Sinnvoller ist aber m.E. das der Implementierungscode einer Klasse alle Windows-OS-Versionen handeln kann.

Carsten1234 25. Mär 2009 06:27

Re: Klassentyp zur Laufzeit ändern
 
Zitat:

Zitat von Bernhard Geyer

Delphi-Quellcode:
if IsVista then
  Application.CreateForm(TVistaForm, frmMain)
else
  Application.CreateForm(TMainForm, frmMain);
Sinnvoller ist aber m.E. das der Implementierungscode einer Klasse alle Windows-OS-Versionen handeln kann.

Bisher habe ich lediglich unter Vista ein paar kl. Darstellungsprobleme von/bei zugekauften GUI-Komponenten. Während unter W2K und XP alles top aussieht, habe ich unter Vista die eben genannten Probleme (mal sehen, wie es unter Windows 7 aussieht). Derzeit behelfe ich mir diesbzgl. mit einer kl. Krücke, aber das ist auch noch nicht sooooo der Hit.

Ich werde das da oben mal testen, Danke dafür.

Gruß, Carsten

alzaimar 25. Mär 2009 06:46

Re: Klassentyp zur Laufzeit ändern
 
Hier ein Hack, mit dem das doch geht:
Delphi-Quellcode:
type
  PClass = ^TClass;

begin
  PClass(MyObjectOfTypeXXX)^ := TDerivedClassFromXXX;
end;
Bei Dir funktioniert das nur, wenn TVistaForm von TMainForm abgeleitet ist.

Viel sauberer wäre folgende Lösung;
Delphi-Quellcode:
Type
  TFormClass = Class Of TMyMainForm;
  TVistaForm = Class (TMyMainForm)...
  TWindows7Form = Class (TMyMainForm)...
  TWINNTForm = Class (TMyMainForm)...

Var
  FormClass : TFormClass;

Begin
// Das hier ist eine Class-Factory (nun ja, wenn sie einmal groß ist)
  Case OSType Of
    Vista : FormClass := TVistaForm;
    Windows7 : FormClass := TWindows7Form;
    ...
  End;
//
  Application.CreateForm (FormClass, MyFormInstance);
...
Such mal unter dem Stichwort: 'Class Factory'.

Carsten1234 25. Mär 2009 07:00

Re: Klassentyp zur Laufzeit ändern
 
Hhhmm, irgendwie bin ich heute morgen noch nicht so ganz wach. :angel2:

Also, bisher leitet sich meine TMainForm wie folgt ab:
Delphi-Quellcode:
  TMainForm = class(TAdvToolBarForm)
  (...)
  end;
Unter Vista habe ich leider die genannten Darstellungsproblemchen, so dass ich (erstmal) speziell für Vista meine TMainForm nicht ableiten möchte von TAdvToolbarForm, sondern schlicht von TForm.
Und hier kann ich noch nicht die Transferleistung erbringen zu Deinem Code. :wall:

Gruß, Carsten

oki 25. Mär 2009 07:08

Re: Klassentyp zur Laufzeit ändern
 
Moin,

Somit hat Bernhadt aber schon recht. Die Klasse eines instanziierten Objektes kann man nicht ändern. Der entscheidende Punkt ist, dass das Objekt mir der passenden Klasse instanziiert wird.

Ich finde alzaimar's Ansatz mir der Metaklasse aber sehr elegant. Dies vorallem, dass nur an einer Stelle die Entscheidung über die richtige Klassenauswahl getroffen werden muss und danach "normal" gecoded werden kann. Umständliche cases auf den BS-Typ an jeder weiteren Stelle im Code kann verzichtet werden was die Fehlerquote rapide senken sollte.

Ich persönlich halte das für eine sehr elegante Lösung und würde diese verwenden. Die Instanz der Form muss aber auf jeden Fall mit der passenden Klasse gebildet werden. Ein nachträgliches Ändern halte ich für nicht akzeptabel oder ehen unmöglich (habe das mit der Zeigerthematik auf die Klasse in alzaimar's Beispiel aber auch noch nicht komplett durchschaut).

Gruß oki

oki 25. Mär 2009 07:15

Re: Klassentyp zur Laufzeit ändern
 
Hi Carsten,

es ist so gemeint, dass du zwei Fensterklassen erstellt. Einmal das von dir beschriebene und dann eins für Vista (sozusagen zwei Formulare).
Beide Fensterklassen "sammelst" du unter einer Metaklasse. Beim Start des Programms wertest du das Betrieblssystem aus und weist deiner Metaklasse die passende Fenserklasse zu. Bei Vista dann den Klassennamen deines Form für Vista. Jetzt kannst du dein MainForm ganz normal mit dem Klassentyp deiner Metaklasse instanziieren, weil du vorher dieser ja den passenden Klassentyp zugewiesen hast. Im gesamten Code arbeitest du dann immer mit dem Metaklassenbezeichner hinter dem sich der richtige Klassentyp verbirgt. Ein aufwendiges Abfragen an jeder Stelle des Codes welches OS läuft entfällt dann.

Gruß oki

Carsten1234 25. Mär 2009 07:21

Re: Klassentyp zur Laufzeit ändern
 
Hallo Oki,

Zitat:

Zitat von oki
es ist so gemeint, dass du zwei Fensterklassen erstellt. Einmal das von dir beschriebene und dann eins für Vista (sozusagen zwei Formulare).

Das bedeutet doch aber im Umkehrschluss, dass ich sämtliche Routinen (z.B. OnClick für einen Button usw.) doppel schreiben muss!?!?!
Einmal für die von mir beschriebene Version und einmal für die Vista-Form.

Gruß, Carsten

oki 25. Mär 2009 07:33

Re: Klassentyp zur Laufzeit ändern
 
nun ja, zumindest für den Teil, der bei Vista anders ist.
Entweder du hast je eine Klasse für jedes OS, dann macht das mit der Klassenänderung auch Sinn. Ob du dabei die Klassen untereinander vererbst oder jede speziell erstellst bleibt dir überlassen.

Deine Frage war ja, ob du die Klasse ändern kannst. Also mußt du auch eine andere Klasse haben. Was soll sonst deine "Vista-Klasse" sein als anderer implementierter Code.

Wenn du nur spezielle wenige Dinge im Code deines Forms anders machen mußt kann du durchaus auch mit einer Klasse arbeiten und in den entsprechenden Abschnitten das OS abfragen und den passenden Code ausführen. Ganz nach belieben.

Gruß oki

shmia 25. Mär 2009 11:06

Re: Klassentyp zur Laufzeit ändern
 
Zitat:

Zitat von oki
Die Klasse eines instanziierten Objektes kann man nicht ändern.

Man kann schon :zwinker: , aber man kann sich damit auch gewaltig in den Fuß schiesen.
Es ist auch möglich, dass der Trick nach dem Wechsel des Compiler nicht mehr funktioniert.
Die neue Klasse muss vor der bisherigen Klasse abgeleitet sein und ausserdem darf die abgeleitete Klasse keine
zusätzlichen Felder haben.
Delphi-Quellcode:
procedure ChangeClass(obj : TObject; NewClass:TClass);
type PClass = ^TClass;
begin
   if Assigned(obj) and (obj.ClassType <> NewClass) then
   begin
      if obj.ClassType <> NewClass.ClassParent then
         raise Exception.CreateFmt('can''t change Object of class %s to class %s', [obj.ClassName, NewClass.ClassName]);
      if obj.InstanceSize <> NewClass.InstanceSize then
         raise Exception.CreateFmt('Class %s - invalid instance size', [NewClass.ClassName]);
      PClass(obj)^ := NewClass;
   end;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:55 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz