Bob Swart (aka Dr.Bob)
Delphi for .NET command-line compiler

Met Delphi naar .NET
Delphi 7 Studio bevat behalve Delphi 7 zelf ook een speciale CD met daarop de Delphi for .NET preview command-line compiler. Dit is een preview editie van de command-line compiler die Delphi source code kan compileren en als resultaat Common Intermediate Language (CIL) kan opleveren, die binnen .NET als safe, managed code kan draaien.
Omdat het slechts een (eerste) preview betreft, hebben we echter nog geen IDE, en zelfs nog geen visuele componenten. Er zijn een beperkt aantal units beschikbaar, maar toch kunnen we hier al wat leuke (en zelfs nuttige) dingen mee doen. Daar ga ik het deze keer over hebben...

Common Language Runtime
De Delphi for .NET Preview bevat een aantal classes en types die we eigen direct kunnen "mappen" op corresponderende .NET runtime types en classes.
Delphi for .NET.NET CLR
TObjectSystem.Object
StringSystem.String
VariantSystem.ValueType
RecordsSystem.ValueType
ExceptionSystem.Exception
TComponentSystem.ComponentModel.Component
Database connectivity ADO.NET (and DataSnap direct drivers) 
RIO Web ServicesOn top of System.Web.Services
GUISystem.Windows.Forms plus VCL

Zie voor meer informatie het artikel van John Kaster en Danny Thorpe op http://dotnet.borland.com.

DCCIL Demos
Tijd om een paar eenvoudige demo toepassingen te bouwen met de Delphi for .NET preview command-line compiler. Om uit vinden wat de mogelijkheden zijn, is het zaak eerst even te kijken naar de units die beschikbaar zijn in deze eerste versie van de preview command-line compiler. Dat zijn de volgende (te vinden in de Delphi for .NET Preview\Source\Rtl directory):

Merk op dat units niet langer simpelweg "System.pas" of "SysUtils.pas" heten, maar een langere naam hebben met daarin Borland.Delphi of Borland.Win32 als prefix. Daar kom ik straks op terug. Voorlopig wil ik met name concluderen dat het maar erg weinig units zijn, zonder specifieke VCL (of CLX) units. Nog geen visuele componenten dus, maar wel een aantal types, routines en normale classes.

In de eerste update van de Delphi for .NET preview command-line compiler (te downloaden sinds 22 november 2002) zijn extra units toegevoegd, namelijk:
  • Borland.Data.FMTBcd.pas
  • Borland.Data.SqlTimSt.pas
  • Borland.Delphi.Classes.pas
  • Borland.Delphi.Contnrs.pas
  • Borland.Delphi.Masks.pas
  • Borland.Delphi.MaskUtils.pas
  • Borland.Delphi.SyncObjs.pas
  • Borland.Delphi.VarConv.pas
  • Borland.Delphi.Variants.pas
  • Borland.Win32.ActiveX.pas
  • Borland.Win32.CommCtrl.pas
  • Borland.Win32.CommDlg.pas
  • Borland.Win32.Dlgs.pas
  • Borland.Win32.Imm.pas
  • Borland.Win32.IniFiles.pas
  • Borland.Win32.Messages.pas
  • Borland.Win32.MultiMon.pas
  • Borland.Win32.Registry.pas
  • Borland.Win32.ShellAPI.pas
  • Borland.Win32.UxTheme.pas
  • Borland.Win32.WinSpool.pas
  • Borland.Win32.WinUtils.pas
De volgende keer gaan we hier dieper op in, en zal ik laten zien wat we met deze eerste (preview) versie van de VCL for .NET kunnen doen.

Overigens bevat de Delphi for .NET preview command-line compiler de precompiled units in .dcua en .dcuil formaat die geschikt zijn voor de originele versie 1.0 van het .NET Framework (eventueel met service pack 1). Wie service pack 2 al heeft toegepast (wie niet?), zal de .dcua en .dcuil bestanden opnieuw moet compileren. Hiervoor is een rebuild.bat bestand gemaakt, dat eveneens te vinden is in de Delphi for .NET Preview\Source\Rtl directory.

Console Demos
Wat kunnen we maken met de paar units die we hebben? En hoe kunnen we toepassingen bouwen voor .NET, zonder visuele IDE? Op dat laatste kom ik straks nog terug, maar laten we beginnen met (Visual) Notepad, om het volgende "Hello World" programma in te tikken:

  program Hello;
  {$APPTYPE CONSOLE}
  begin
    writeln('Hello, world!');
  end.
Met dccil kunnen we Hello.dpr (zie boven) compileren tot een hele kleine Hello.exe - een .NET executable die bestaat uit safe, managed code. Weinig bijzonders tot nu toe, nietwaar? Laten we eens iets meer doen, en de GetCurrentDir functie uit de SysUtils gebruiken:
  program CurrDir;
  {$APPTYPE CONSOLE}
  uses
    {$IFDEF CLR}Borland.Delphi.{$ENDIF}SysUtils;
  begin
    Writeln(GetCurrentDir);
    readln;
  end.
Merk op dat {$IFDEF CLR} de compiler directive is om code voor CLR (Common Language Runtime) te onderscheiden van code voor Windows of Linux (waar {$IFDEF MSWINDOWS} voor Windows en {$IFDEF LINUX} aangeeft dat we voor Linux compileren). En behalve het feit dat we de CLR versie van de SysUtils unit willen gebruiken, is in de source code ook duidelijk te zien dat onder CLR gebruik wordt gemaakt van een nieuwe manier om units te identificeren: met namespaces. De Borland.Delphi.SysUtils is een unieke naam om de unit te identificeren (iets wat we al eerder zagen).

Visuele Demos
Laten we nu eens kijken hoe een visuele toepassing eruit kan zien. Ik moet je hierbij wel waarschuwen dat we nu nog niet van VCL controls gebruik zullen maken, maar aanwezen zijn op de .NET classes binnen bijvoorbeeld System.Windows.Forms (van Microsoft). Gelukkig lijkt die in vele opzichten op de Forms die we uit Delphi kennen, net als de Button control bijvoorbeeld.
Een wat groter probleem is het ontbreken van een IDE met Form Designer (en Object Inspector), zodat we ook nu aangewezen zijn op Notepad om de code in te tikken. Waar dat geen probleem gaf bij de bouw van simpele console toepassingen, is het natuurlijk een andere zaak als we visuele toepassingen willen bouwen. Gelukkig kunnen we in de constructor van het Form een hoop dingen doen, zoals de button explicitiet creeëren, de posities zetten, en zelfs de caption een waarde geven, bijvoorbeeld als volgt:

  program Sample;
  uses
    System.Windows.Forms,
    System.ComponentModel,
    System.Drawing;

  type
    TForm42 = class(Form)
    private
      FButton: Button;
    public
      constructor Create;
    end;

  constructor TForm42.Create;
  begin
    inherited Create;
    FButton := Button.Create;
    FButton.Location := Point.Create(184, 176);
    FButton.Name := 'Button';
    FButton.TabIndex := 0;
    FButton.Text := 'Hello';
    Controls.Add(FButton)
  end;

  var
    Form42: TForm42;
  begin
    Form42 := TForm42.Create;
    Form42.Text := 'Bob Swart Training && Consultancy';
    Application.Run(Form42)
  end.
Merk op dat we de positie van de Button niet opgeven met behulp van de Top, Left, Height en Widt properties, maar met de Location property die de linkerbovenhoek van de button aangeeft (we kunnen dan met de Size property de hoogte en breedte aangeven).
Een button op een form is leuk, maar nutteloos als het niks doen. Event handlers werken ook een beetje anders in .NET, en de Click event handler van de button moeten we dan ook met behulp van de add_Click methode toevoegen (de "design pattern" hier is add_XXX voor de event handler XXX). De event handler routine zelf is ook anders, want we krijgen niet alleen de Sender als eerste argument, maar tevens de "event arguments" als tweede argument. De OnClick event handler (die we met add_Click kunnen toevoegen aan het Click event) ziet er dan ook als volgt uit:
  procedure OnClick(Sender: System.Object; eventArgs: System.EventArgs);
Los van het feit dat de event handler dus twee in plaats van één argument heeft (en dat we de add_Click moeten gebruiken), werkt het verder bijna net als in "gewoon" Windows. Een extra verschil is nog dat er meerdere event handlers aan een event gehangen kunnen worden (daar kom ik later ook nog op terug).
Als voorbeeld van het gebruik van event handlers kun je naar onderstaand programma kijken waarin we een event handler koppelen aan de Click events van drie verschillende buttons. Afhankelijk van de button waarop geklikt is (de Sender) doen we iets speciaals, namelijk de kleur van de button veranderen. Simpel, maar het laat in ieder geval zien hoe een-en-ander in zijn werk gaat.
  program Controls;
  uses
    System.Windows.Forms,
    System.ComponentModel,
    System.Drawing;

  type
    TForm42 = class(Form)
    private
      procedure OnClick(Sender: System.Object; eventArgs: System.EventArgs);
    public
      constructor Create;
    end;

  { Form42 }

  constructor TForm42.Create;

    function MakeButton(const AText: String; X, Y: Integer): Button;
    begin
       Result := Button.Create;
       Result.Text := AText;
       Result.Location := Point.Create(X, Y);
       Result.Size := Size.Create(50, 50);
       Result.add_Click(OnClick)
     end;

  begin
    inherited Create;
    Text := 'Delphi for .NET preview';
    Controls.Add(MakeButton('Red', 100, 50));
    Controls.Add(MakeButton('Blue', 100, 100));
    Controls.Add(MakeButton('Green', 100, 150))
  end;

  procedure TForm42.OnClick(Sender: System.Object; eventArgs: System.EventArgs);
  var
    Btn: Button;
  begin
    Btn := Button(Sender);
    if Btn.Text = 'Red' then Btn.BackColor := Color.Red else
    if Btn.Text = 'Blue' then Btn.BackColor := Color.Blue else
    if Btn.Text = 'Green' then Btn.BackColor := Color.Green
  end;

  begin
    Application.Run (TForm42.Create)
  end.
De volgende keer zal ik dieper ingaan op de VCL for .NET die met de update van de Delphi for .NET preview command-line compiler beschikbaar is gekomen.

Delphi for .NET en ASP.NET
De Delphi for .NET preview command-line compiler is ook te gebruiken als scripting taal binnen ASP.NET. Dit betekent concreet dat we bestaande Delphi code (en ervaring) kunnen hergebruiken als scripting code binnen ASP.NET pagina's. Een heel klein voorbeeld betreft bijvoorbeeld het converteren van temperatuurwaarden, van Celsius naar Fahrenheit, wat door de volgende ASP.NET pagina gedaan wordt (merk op dat de twee event handlers gewoon Delphi code zijn):

  <html>
  <head>
  <title>Delphi for .NET does ASP.NET</title>
  <script language="Delphi" runat="server">

    procedure CelsiusToFahrenheitClick(Sender: System.Object; E: EventArgs);
    begin
      edtFahrenheit.Text := Convert.ToString(9 / 5 *
        Convert.ToDouble(edtCelsius.Text) + 32);
      Message.Text := 'Celsius to Fahrenheit'
    end;

    procedure FahrenheittoCelsiusClick(Sender: System.Object; E: EventArgs);
    begin
      edtCelsius.Text := Convert.ToString(5 / 9 * 
        (Convert.ToDouble(edtFahrenheit.Text) - 32));
      Message.Text := 'Fahrenheit to Celsius'
    end;

  </script>
  </head>

  <body bgcolor="ffffcc">
  <font face="verdana" size="2">
  <form runat="server">
     <br><b>Celsius:</b> <asp:textbox id="edtCelsius" runat="server"/>
     <br><b>Fahrenheit:</b> <asp:textbox id="edtFahrenheit" runat="server"/>
     <p>
     <asp:button text="Celsius to Fahrenheit" OnClick="CelsiusToFahrenheitClick" runat="server"/>
     <asp:button text="Fahrenheit to Celsius" OnClick="FahrenheittoCelsiusClick" runat="server"/>
  </form>
  <hr>
  Last conversion performed:
  <b><asp:label id="Message" runat="server"/></b>
  </body>
  </html>
De Celsius naar Fahrenheit omzetter is op het internet beschikbaar om zelf uit te proberen.

Meer Informatie
Mocht iemand nog vragen, opmerkingen of suggesties hebben, dan hoor ik die het liefst via . Wie meer wil zien betreffende Delphi en de samenwerking met .NET, zou zeker een bezoek aan mijn Delphi en .NET Clinic kunnen overwegen.


This webpage © 1999-2006 by webmaster drs. Robert E. Swart (aka - www.drbob42.com). All Rights Reserved.