![]() |
AW: Reise von Berlin nach Athens
Dafür ist nicht zwingend ein Hook notwendig. Erstelle eine Unit mit folgendem Inhalt:
Delphi-Quellcode:
Diese Unit muss dann in allen Forms und DataModules als letztes in der Interface Uses-Anweisung stehen.
unit FixOldCreateOrder;
interface uses System.Classes, Vcl.Forms; type TDataModuleFix = class(TDataModule) protected procedure Loaded; override; end; type TFormFix = class(TForm) protected procedure Loaded; override; end; type TForm = TFormFix; implementation procedure TFormFix.Loaded; begin inherited; OldCreateOrder := False; end; procedure TDataModuleFix.Loaded; begin inherited; OldCreateOrder := False; end; end. Im Designer steht dann zwar immer noch OldCreateOrder als True, aber das hat ja keine direkten Auswirkungen. Beim Programmstart wird das entsprechend korrigiert. Für etwaige Abkömmlinge von TCustomActiveForm und TCustomDockForm müsste das dann entsprechend ergänzt werden. |
AW: Reise von Berlin nach Athens
Weiß nicht genau ... frühestens im 10.2 oder vielleicht erst 11.0.
irgendwo zwischen XE und 10.4 In DFM wird ja "inzwischen" normal ClientWidth/ClientHeight gespeichert, aber abhängig von anderen Property wird stattdessen Width/Height gespeichert (was ich teilweise für total schwachsinnig halte). Auch andere Property haben solche abweichungen. Und da Emba manchmal Probleme hatte, im Create auf das ClientWidth/ClientHeight zuzugreifen (Exception), wird das in einer Variable gespeichert, welcher erst im AfterConstruction angewendet wird. Wird aber nach ClientWidth etwas an Width zugewiesen, dann wird jenes somit vom ClientWidth wieder "falsch" überschrieben. Lösung war einfach im Width ein FClientWidth:=0; und fertig, aber neeeeeeeeeeee. ![]() . ![]() ![]() ... Im Programm kann man sich da problemlos in seine FormKlasse oder einen Vorfahren die Setter überschreiben und es reparieren, aber im FormDesigner kommt man nur per Hook dran. (bei uns sind deswegen zusammen mehrere Wochen an Arbeitszeit draufgegangen, für etwas, das Emba hätte mit zwei Zeilen Code lösen können) Zitat:
Wenn du das dort, an dieser Stelle, änderst, dann wird/kann kann es passieren, dass OnCreate doppelt ausgeführt wird, im alten Delphi. Im Constructor, da der den Wert aus DFM beachtet wird, dann schreibt Loaded es um und AfterConstruction sieht den neuen Wert und macht es nochmal. :duck: War mir vor kurzem einmal aufgefallen, da im OnCreate eine TComponent erstellt wurde und es dann hieß "Name gibt es schon *peng*". |
AW: Reise von Berlin nach Athens
Zitat:
Selbst wenn man den Constructer überschreibt, ist vor dem inherited noch keine DFM geladen und nach dem inherited das Loaded bereits ausgeführt. Damit is Loaded eine sichere Stelle den Wert passend zu setzen. Übrigens ist das Verfahren keine echte (visuelle) Formvererbung, da ja alle Forms weiterhin von TForm abgeleitet bleiben und in der DFM steht auch object und nicht inherited. Man muss nur die Unit in die davor stehende uses-Anweisung setzen. |
AW: Reise von Berlin nach Athens
Um es nochmals zu trennen
* einmal OldCreateOrder, bei uns zwischen XE und D11 * und andererseits LadeProbleme im D11, z.B. bei ClientWidth und Width, mit Zuweisung im Code (Create bzw. OnCreate) sowie Unterschiede zwischen DFMs bezüglich der FormVererbung z.B. in VorfahrDFM ClientWidth und in NachfahrDFM mit Width, oder Width im Create oder OnCreate und ClientWidth in DFM. Es gab immer wieder irgendwo ein paar Sonderfälle, wo es mit dem OldCreateOrder:=False; irgendwo nicht mehr ging. In DFM mit False, in DFM mit True, nicht in DFM oder teilweise in DFM und dann auch noch unterschiedlich, ... Wir haben hier aber auch eine wilde Mischung. * im Delphi mit FormVererbung (mehrere DFM pro Form) * über den Greatis FormDesigner die DFM zur Laufzeit aus der Datenbank * manuell zur Laufzeit die DFM aus der Datenbank (TReader.ReadRootComponent) Ich glaub ganz zu Beginn hatte Emba im DataModul das Ignore-OldCreateOrder vergessen und dann knallte es, wenn das noch in der DFM stand. Da wir zur Laufzeit fehlerhafte Property ignorieren, ähnlich wie im FormDesigner der IDE (wobei wir ebenfalls den Fehler abgangen und ins Log schreiben, bzw. anzeigen, anstatt abrauchen zu lassen) Dem TReader.OnError im Form.ReadState etwas zugewiesen und darin Handled=True. Den letzten Fall, wo OnCreate doppelt ausgeführt wurde, hatte ich dann so abgefangen. Da wir die Stelle nicht fanden, wo/warum hier OldCreate immernoch/wieder True war, wurde letztendlich einfach das erste OnCreate (hier im inherited) unterdrückt.
Delphi-Quellcode:
Loaded ist aber auch nicht deterministisch.
procedure TCimBaseForm.DoCreate;
begin { TODO -oUmstieg XE DX/D11 -cUmstieg XE DX/D11 : Dieses Handling kann entfernt werden, sobald kein XE mehr benutzt wird } // Delphi 11 löscht OldCreateOrder, weil es seit längerem nicht mehr benutzt wird // Delphi XE fügt im FormDesigner OldCreateOrder:=True; ein, wenn es das Property (noch) nicht findet. Es muß aber False sein/bleiben. {$IFDEF VER220 DelphiXE} // Wenn OldCreateOrder=True in DFM steht dann kommst es schon im Constructor hier vorbei, aber es darf erst im AfterConstrution hier ankommen. // Außer dem StackTrace hab ich aber nichts gefunden, was hier erkennen lässt, wer das aufruft. // Im AfterConstruction ist es aber definitiv False, da siehe TCimBaseForm.Create, somit kann es hier eigentlich nur noch vom Constructor kommen // und in diesem Fall wird OnCreate nicht ausgefürt, da es sonnst doppelt ausgeführt wird, also nochmal in AfterContruction, und es dann knallt. if OldCreateOrder then begin OldCreateOrder := False; Exit; end; {$ENDIF} try inherited; except Exception.InsertStackInfo(SecureFullName('TCimBaseForm') + '.DoCreate'); // TCustomForm.DoCreate - TCustomForm.HandleCreateException -> Application.HandleException -> THauptForm.ApplicationEvents1Exception -> CimShowExceptionDialog end; end; Vor allem bei FormVererbung und/oder Kreuzreferenzen von Forms/Datenmodulen/Komponenten, wird das verzögert. z.B. auf einer Form ein TDBEdit und eine TDataSource, aber das Edit vor der DataSource in der DFM, dann kann dem Edit.DataSource die DataSource noch nicht zugewiesen werden, somit ist beim DBEdit.Loaded dieses Property noch nicht gesetzt, da es dann erst ganz am Ende zugewiesen wird und dann da nochmals dessen Loaded. Das betrifft auch DatenModule und Frames, wo nach dem Laden dieser eventuell erst viel Später, also nach dem Laden aller zusammengehörenden Forms/Frames/Datenmodule die fehlenden Referenzen aufgelöst werden und erst dann das Loaded ausgelöst wird. (z.B. GlobalFixupReferences) |
AW: Reise von Berlin nach Athens
Ein text-suchen-und-erstzen nach OldCreateOrder in PAS und DFM dateien geht nicht?
Dann hat man halt ne D12 code base und gut , oder ? |
AW: Reise von Berlin nach Athens
Delphi 12 ist hier nicht das Problem (des löscht es von alleine raus).
Dort gibt es inzwischen auch einen Code, welcher dieses Property beim DFM-Lesen ignoriert, da es dieses Property an der Formklasse nicht mehr gibt und es beim Laden sonst knallen würde. Problem ist, wenn eine Form in D11/D12 bearbeitet und gespeichert wurde, dass es dann im alten Delphi Probleme damit gibt, wenn D11/D12 dieses Property gelöscht hat und das alte Delphi denkt diese DFM kommt aus einem ganz extrem uralten Delphi und es dieses Property "falsch" wieder einfügt (True statt False). z.B. wenn man parallel mit zwei/mehr DelphiVersionen arbeitet, bzw. man seinen Code noch abwärtskompatibel zur alten Version halten muß, weil eventuell der aktuelle ReleaseBranch und alte ReleaseBranches für Bugfixes noch mit dem alten Delphi arbeiten, während man in Master-/Bug-/FeatureBranches schon mit dem neuen Delphi rumspielt, bzw. man alles noch auf alt lauffähig hält, falls es im neuen Delphi D11 weitere unzumutbare Probleme gibt und man notfalls wieder zurück zum XE will/muß. |
AW: Reise von Berlin nach Athens
Oki,
es läuft schon mal nicht schlecht. Ich habe jetzt eine saubere Trennung der Quelltexte vom Berlin und Athens gemacht - damit es keine Überschneidungen gibt, die seltsame Fehler auslösen. Jetzt gerade habe ich das Problem - was im Berlin kein Problem war - mit einer Meldung: Zitat:
Ich hätte sie natürlich auch ShowMessage1 oder so nennen können, dann aber an hunderten Stellen es so ändern müssen - so ging es einfach am schnellsten. Ich habe in der Unit die Deklaration so gemacht:
Delphi-Quellcode:
Und obwohl das (für Berlin scheinbar) korrekt deklariert ist, meckert Athens herum. :pale:
procedure ShowMessage(const Msg: string; icon:char='i'; color:TColor = clBlue); overload;
implementation procedure ShowMessage(const Msg: string;icon:char='i'; color:TColor = clBlue); overload; //Icon: 0:i 1:? 2:X 3:! begin // hier mein modales Fenster konfigurieren und anzeigen end; Lasse ich "zur Deklaration springen" - öffnet es "Vcl.Dialogs" bei Showmessage. Es ignoriert also meine lokale Deklaration. Muss das über einen Compiler-Schalter, der das zulässt/vermeidet, bestimmt werden? |
AW: Reise von Berlin nach Athens
Schmeiß den Searchbot an und lass alles per globalem Suchen und Ersetzen zu einer vernünftig bezeichneten Methode umbenennen. ZB: SBShowMessage. Die paar vorkommenden "echten" ShowMessage Aufrufe korrigierst Du dann händisch zurück. Kompilerschalter haben immer den Hauch des vorübergehenden...
|
AW: Reise von Berlin nach Athens
Denk dir die/deine Default-Parameter weg
und was bleibt nun übrig?
Delphi-Quellcode:
//procedure ShowMessage(const Msg: string; icon:char='i'; color:TColor = clBlue);
Delphi-Quellcode:
procedure ShowMessage(const Msg: string);
also das Selbe, wie's Andere,
Delphi-Quellcode:
procedure ShowMessage(const Msg: string);
somit genau das, was dir die Fehlermeldung sagt. |
AW: Reise von Berlin nach Athens
Okay, dann mach ich das.
Aber schon interessant, daß das Berlin hierbei schlauer war als jetzt das Athens und es nicht als Fehler bemängelte, sondern richtig gemacht hatte. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:09 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