|
Registriert seit: 9. Sep 2003 Ort: Wildeshausen 295 Beiträge Turbo Delphi für Win32 |
#1
Moin Leute
![]() Wie schon länger angekündigt möchte ich nun meine Konvertierung von Turbo-Pascal 7.0 in Delphi vorstellen. Das ist mein Meilenstein in der DP. Es gibt bestimmt noch so ein paar arme Schweine wie ich, die so ein altes grottiges Ding pflegen müssen. Für mich war es eine Menge Arbeit, bis meine Anwendung entlich als Konsole lief. Ich erzähle mal nicht von den vielen Stolpersteinen sondern von dem Weg, den man gehen muss. Es lohnt sich auf jeden Fall. Unter Delphi hat man die ganzen Begrenzungen nicht, die unter DOS so waren. Reichlich Speicher, deutlich näher an 32 Bit, den Drucker direkt ansprechen ohne Zwischenprogramm, uswusf. Der erste Akt: FindFirst/FindNext/FindClose Hätte ich die ganzen Stellen mit Compilerschaltern versehen, wäre ich heute noch dabei. Also habe ich alle Stellen so umgestellt, dass fast alles über dieses Objekt läuft.
Delphi-Quellcode:
In diesem kleinen Anfang merken einige von euch, wohin der Hase läuft. Es gibt ein paar Stellen dann nur noch wo man mit Kompilerschaltern arbeiten muss.
type
TDirInfo = object {$IfDef Win32} private FDoFindClose : Boolean; public {$EndIf} DirInfo : TSearchRec; constructor Create; function FindFirst( aDatei : PathStr; aAttr : Word):Boolean; function FindNext:Boolean; destructor Free; end; constructor TDirInfo.Create; begin {$IfDef Win32} FDoFindClose := False; {$EndIf} end; function TDirInfo.FindFirst( aDatei : PathStr; aAttr : Word):Boolean; {$IfDef Win32} var lEc : Int32; {$EndIf} begin {$IfDef Win32} if FDoFindClose then SysUtils.FindClose(DirInfo); lEc := SysUtils.FindFirst(aDatei,aAttr,DirInfo); if lEc = 0 then begin FDoFindClose := True; FindFirst := True; end else begin FindFirst := False; end; {$Else} Dos.FindFirst(aDatei,aAttr,DirInfo); FindFirst := DosError = 0; {$EndIf} end; function TDirInfo.FindNext:Boolean; {$IfDef Win32} var lEc : Int32; {$EndIf} begin {$IfDef Win32} lEc := SysUtils.FindNext(DirInfo); FindNext := lEc = 0; {$Else} Dos.FindNext(DirInfo); FindNext := DosError = 0; {$EndIf} end; destructor TDirInfo.Free; begin {$IfDef Win32} if FDoFindClose then SysUtils.FindClose(DirInfo); {$EndIf} end; Die Variable InOutRes gibt es unter Delphi nicht. Hier gibt es aber die Prozedur SetInOutRes die ich dann überall verwende. So ist sie dann im TP eingebunden. Das Umstellen des Quelltextes von InOutRes auf SetInOutRes übernimmt dann die Konvertierung. Dazu später mehr.
Delphi-Quellcode:
Der zweite Akt: Fail in Konstruktoren
{$IfNDef Win32}
procedure SetInOutRes( aEc : Int_Int); begin InOutRes := aEc; end; {$EndIf} Ein Konstruktor darf nur aus Speichermangel in das Fail laufen. Ich hatte das für allmöglichen Kram genutzt. Das wird jetzt reine Handarbei. Ich bin einfach dabeigegangen und habe alle Stellen mit "{ok}" markiert, wo das Fail durch einen Speichermangel ausgeführt werden könnte. Unter Delphi passiert das eh nicht, da gibt es kein MemAvail und MaxAvail. Unter Kompilerschalter habe ich die Funktionen selbst geschrieben und einfach Max(Int32) übergeben. Die nativen Typen erkläre ich gleich. Alle anderen Stellen müssen so überarbeitet werden, dass das Fail rausfliegt. Einfach den Konstruktor mit weniger Parameter aufrufen und eine weitere Funktion mit der extrahierten Arbeit beauftragen. Ja, das kann verdammt viel werden und lange dauern. Der dritte Akt: Auf Funktionalität verzichten Ich habe Modemgeschichten und Grafikausgaben einfach deaktiviert. Falls jemand diesen Teil noch braucht, ist das kein Problem. Ich kann mein FOS als DOS- und Win32-Applikation kompilieren. Wer den alten "Mist" noch braucht, soll das DOS-Programm starten. Beim deaktivieren Kompilerschalter verwenden! Der vierte Akt: Die Hauptdatei In der Hauptdatei sind nur noch die Uses-Anweisung, ein Include-Aufruf und im Programmblock der Start der Anwendung. Auf diese Art wird dann später auch die DPR erstellt. So sieht jetzt die PAS-Datei aus:
Delphi-Quellcode:
Und ein Einblick in die DPR-Datei:
program FOSdos;
{$M 65500,0,655360} uses FosOver,Overlay, FosChars,Crt,Dos,Fosmenue,Fostast,Fosfiles,Fosunter, Fosan,Fosbuch,Foscheck,Fosmanam,Fospersm,Fosterm,Fosakt,Fosmastm, Fostunde,Fosgrund,FosGrun2,Foslizen,FosMBox,FosRout,FosDyna,FosBase, FosRout2,FosRout3,FosObj,FosAbsch, FosMUnit, FosTEdit,FosBrows,FoStatik, FosInput,Netzwerk,FosGlob,FoSchon,FosMonov,FoSerie,FosBitL, FosDebug, FosDump, FosRes,fosdatum,FosDialo,FoSicher,FosPrint,FosBruch, FosCMD,FoShell,FosTime,FosMask,Fos2dStr,FosKMenu,FosArchi,FosAn2, FosWork,FosXMS,FosNInfo,Drucken,Killer,PipeStr,DruckObj,Vorbest, HeapUse, {$IFNDEF DPMI} ShowHeap, {$ENDIF DPMI} Einstell,KeyLoop,Kasse,Connect,Mouse, Vorlagen,BestWerb,Ortsteil,Bondruck,Kalender,Tastatur,RecBaseU, FosMPack; {$O ShowHeap.Pas} {$O GDISupp.Pas } {$O FosLZSS.Pas } {$O FORMULAR.PAS} {$O FOSDIALO.PAS} {$O FOSOBJ.PAS } {$O FosInput.Pas} {$O FosWork } {$O FoSerie.Pas } {$O FOSABSCH.PAS} {$O FOSAKT.PAS } {$O FOSAN.PAS } {$O FOSAN2.PAS } {$O FOSARCHI.PAS} {$O FOSBASE.PAS } {$O FosBitL.Pas } {$O FOSBROWS.PAS} {$O FosBruch.Pas} {$O FOSBUCH.PAS } {$O FOSCHECK.PAS} {$O FosCMD.Pas } {$O FosDebug.Pas} {$O FosDump.Pas } {$O FoShell.Pas } {$O FoSicher.Pas} {$O FOSLIZEN.PAS} {$O Netzwerk.Pas} {$O FOSMANAM.PAS} {$O FOSMASTM.PAS} {$O FOSMBOX.PAS } {$O FosMCons.Pas} {$O FOSMENUE.PAS} {$O FosMHelp.Pas} {$O FosMonoV.Pas} {$O FosMPack.Pas} {$O FosMUnit.Pas} {$O FOSPERSM.PAS} {$O FosPrint.Pas} {$O FOSTAPEL.PAS} {$O FoStatik.Pas} {$O FosTEdit.Pas} {$O FOSUNTER.PAS} {$O FosMask.Pas } {$O Fos2dStr } {$O FosKMenu } {$O FosXMS } {$O FosNInfo } {$O Drucken } {$O Killer } {$O DruckObj } {$O Vorbest } {$O Einstell } {$O Formular } {$O Kasse } {$O Connect } {$O Mouse } {$O Vorlagen } {$O BestWerb } {$O Ortsteil } {$O Tastatur } {$O Kalender } {$O KMenu2 } {$O Bondruck } {$O FosRes } {$O FOSFILES.PAS} {$O Fostunde } {$O PipeStr } {$I Fosystem.Inc} begin Haupt; end.
Delphi-Quellcode:
Schön zu sehen ist die Prüfung auf mindestens einen installierten Drucker und dass GetTickCount nicht überläuft. Auch schön zu sehen, wie ich mit Umlauten umgehe. Die Konvertierung stellt alle Sonderzeichen als Konstante dar.
program Fosystem;
{$APPTYPE CONSOLE} uses {$IfDef Win32}SysUtils,FosDelphi,{$EndIf} BestWerb in 'BestWerb.pas', Bondruck in 'Bondruck.pas', Connect in 'Connect.pas', Crt in '.\Units\Crt.pas', Dos in '.\Units\Dos.pas', Drucken in 'Drucken.pas', DruckObj in 'DruckObj.pas', Einstell in 'Einstell.pas', Formular in 'Formular.pas', Fos2dStr in 'Fos2dStr.pas', Fosabsch in 'Fosabsch.pas', Fosakt in 'Fosakt.pas', Fosan in 'Fosan.pas', Fosan2 in 'Fosan2.pas', Fosarchi in 'Fosarchi.pas', Fosbase in 'Fosbase.pas', FosBitL in 'FosBitL.pas', FosBrows in 'FosBrows.pas', FosBruch in 'FosBruch.pas', Fosbuch in 'Fosbuch.pas', Foschars in 'Foschars.pas', Foscheck in 'Foscheck.pas', FoSchon in 'FoSchon.pas', FosCMD in 'FosCMD.pas', FosDatum in 'FosDatum.pas', FosDebug in 'FosDebug.pas', FosDialo in 'FosDialo.pas', FosDyna in 'FosDyna.pas', FoSerie in 'FoSerie.pas', Fosfiles in 'Fosfiles.pas', FosGlob in 'FosGlob.pas', FosGrun2 in 'FosGrun2.pas', FosGrund in 'FosGrund.pas', FoShell in 'FoShell.pas', Fosicher in 'Fosicher.pas', FosInput in 'FosInput.pas', FosKMenu in 'FosKMenu.pas', Foslizen in 'Foslizen.pas', Fosmanam in 'Fosmanam.pas', FosMask in 'FosMask.pas', Fosmastm in 'Fosmastm.pas', FosMBox in 'FosMBox.pas', Fosmenue in 'Fosmenue.pas', FosMonoV in 'FosMonoV.pas', FosNInfo in 'FosNInfo.pas', FosObj in 'FosObj.pas', Fospersm in 'Fospersm.pas', FosPrint in 'FosPrint.pas', FosRes in 'FosRes.pas', FosRout in 'FosRout.pas', FosRout2 in 'FosRout2.pas', FosRout3 in 'FosRout3.pas', FoStapel in 'FoStapel.pas', Fostast in 'Fostast.pas', FoStatik in 'FoStatik.pas', FosTEdit in 'FosTEdit.pas', Fosterm in 'Fosterm.pas', FosTime in 'FosTime.pas', Fostunde in 'Fostunde.pas', Fosunter in 'Fosunter.pas', FoSWork in 'FoSWork.pas', GDISupp in 'GDISupp.pas', Graph in '.\Units\Graph.pas', HeapUse in 'HeapUse.pas', Kalender in 'Kalender.pas', Kasse in 'Kasse.pas', KeyLoop in 'KeyLoop.pas', Killer in 'Killer.pas', KMenu2 in 'KMenu2.pas', Mouse in 'Mouse.pas', Netzwerk in 'Netzwerk.pas', Ortsteil in 'Ortsteil.pas', PipeStr in 'PipeStr.pas', Printers, RecBase in 'P:\RecBase\RecBase.pas', RecBaseU in 'RecBaseU.pas', SListDOS in 'SListDOS.pas', Statik2 in 'Statik2.pas', Tastatur in 'Tastatur.pas', Vorbest in 'Vorbest.pas', Vorlagen in 'Vorlagen.pas', Windows, XmsEmu in '.\Units\XmsEmu.pas'; {$I Fosystem.Inc} var lCount : Int32; lTicks : DWord; begin lCount := Printer.Printers.Count; if lCount > 0 then begin lTicks := GetTickCount; if lTicks < 3974400000 then {46 Tage * 24 Stunden * 60 Minuten * 60 Sekunden * 1000} begin try Haupt; except on E:Exception do begin MessageDlg(symStop ,'Exception aufgetreten (' + E.ClassName + '):'#13 +BreakStrToStrList(AnsiToAscII(E.Message),70,255) ,mdxEnter + mdxEsc ,mdpMitte); end; end; end else begin WriteLn('Der Rechner l' + _aumlk + 'uft schon l' + _aumlk +'nger als 45 Tage. Bitte neu starten.'); Write('Enter dr' + _uumlk + 'cken...'); ReadLn; end; end else begin WriteLn('Es ist kein Drucker unter Windows installiert!'); Write('Enter dr' + _uumlk + 'cken...'); ReadLn; end; end. Der fünfte Akt: XMS-Speicher Unter Delphi werden die DOS-Funktionen nicht unterstützt. Da ich über ein Objekt den Speicher verwendet habe, arbeitet mein Delphi-Objekt einfach mit Heap-Speicher und tut so, als ob es XMS sein. Dem Programm ist das egal, hauptsache es läuft wie vorher. So, grobe Vorarbeit ist getan. Mit den Umstellungen und vielleicht ein paar Erneuerungen kann man locker ein Release ausliefern, das Ding läuft genauso wie vorher. Verwendete Typen: Das Dilemma kennen sicherlich einige, die Source für TP und Delphi schreiben mussten. Ich habe das mit klaren Typen umschifft.
Delphi-Quellcode:
Jetzt höre ich schon einen Aufschrei! Ist der bekloppt? Weiß der, wie oft diese Typen verwendet wurden?
{$IfDef Win32}
Int16 = SmallInt; Int32 = Integer; Word_Int = Integer; Int_Int = Integer; Int32_Cardinal = Cardinal; {$Else} Int16 = Integer; Int32 = LongInt; Word_Int = Word; Int_Int = Integer; ShortString = string; Int32_Cardinal = LongInt; TSearchRec = SearchRec; TFileRec = FileRec; TextFile = Text; {$EndIf} KLAR! Die Umstellung übernimmt die Konvertierung. Schon sieht das ganze viel geschmeidiger aus. Es bedarf natürlich eine Menge Handarbeit. SetInOutRes() will in Dos Int16 und in Delphi Int32 haben. Über den Typ Int_Int(vor dem Unterstrich DOS, hinter dem Unterstrich Delphi) ist das simpel gelöst. Was ist mit den DOS-Units? Crt.pas gibt es im Netz. Wo ich meine gefunden habe, weiß ich nicht mehr. In der Unit steht das drin:
Delphi-Quellcode:
DOS.pas habe ich selbst aufgesetzt:
(*-------------------------------------------------------------------------
Portions Copyright (c) 1988-2003 Borland Software Corporation Portions Copyright (c) 2006-2009 W.Ehrhardt Disclaimer: =========== This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. If you use this code, please credit me and keep the references to the other authors and sources. Description: ============ This unit is a light version of Will DeWitt's code with several bug fixes (especially readkey, extended key codes etc). Will's 'unit was based heavily off of the Borland CBuilder 5 RTL'. Because of the unclear licence status of Will's unit, my CRT source is not under zlib license. Anyway, in this unit the code from Will/Borland is radically rewritten and rearranged. The guiding requirement was to make it almost BP7 compatible. The basic idea for separate hardware/software sound support is from Rudy Velthuis' freeware console, but the implementation is different. The supported keys for line editing are from BP7 (^A, ^H, ^D, ^F, ^M, ^S, ^Z), the paradigm shift from readkey to keypressed for doing the dirty work is from FP. The key codes / translations / functionalities were taken from the Phoenix BIOS book and a test program compiled with BP7. There is still work to be done for some rare special extended keys, but this work is delayed to bugfixes or problem reports. -------------------------------------------------------------------------*)
Delphi-Quellcode:
Graph.pas ist bei mir voll das fette Teil:
unit DOS;
interface type PathStr = string[79]; DirStr = string[67]; NameStr = string[8]; ExtStr = string[4]; implementation begin end.
Delphi-Quellcode:
Die sollte man vor dem ersten Kompilieren unter Delphi anlegen. Ich hatte zum Anfang überall die Aufrufe mit Kompilerschalter versehen, bis ich auf die Idee mit den leeren Units gekommen bin.
unit Graph;
interface implementation end. Ich hänge die Konvertierung einfach mal komplett dran. Ich habe zum Anfang von einem Ordner in einen anderen Konvertiert. So konnte ich immer wieder in beiden Systemen kompilieren und Stück für Stück nacharbeiten. Unter TP ist dabei das führende System. Ich habe auch mal ein Stück unter Delphi programmiert. Wenn das dann in Ordnung war, habe ich das gleich in den Dosen-Source eingebaut, um die Konsistenz zu wahren. Ich wünsche Viel Spaß bei der Umstellung Stefan
Englisch eine Weltsprache? Zu kompliziert und der nahe Osten würde Englisch als Pflichtweltsprache nicht akzeptieren.
IDO wäre genau das Richtige: ![]() ![]() |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |