Bob Swart (aka Dr.Bob)
Delphi 3 ActiveForms

Een ActiveX control is een 32-bits OLE control, die vroeger ook wel OCX controls werden genoemd (maar Microsoft moest de naam weer eens wijzigen). Het voordeel van ActiveX is dat het een door Microsoft gedefinieerde standaard is: onder Win32 is het dan ook een veelvoorkomend fenomeen. Sterker nog: het is inmiddels zo'n beetje de grootste gemene deler geworden van alle Windows ontwikkelomgevingen (naast "gewone" EXE executables en DLL dynamic link libraries). Hierdoor kan vrijwel elke 32-bits omgeving onder Windows gebruik maken van ActiveX controls, en kunnen er een heleboel ze ook maken. Waaronder Delphi 3, natuurlijk, onder de veelzeggende naam "One Step ActiveX". De 'waarde' van ActiveX controls is de laatste tijd zelf toegenomen door de ondersteuning van Microsoft Internet Explorer 3.0 en hoger, waardoor ook het internet (of met name eigenlijk het intranet maar daar komen we nog op) hier voor een toename van de hype zorgt.
Voor we nu allemaal gaan staan juichen, wil ik eerst een van de nadelen van ActiveX controls benadrukken: Een ActiveX control is een zelfstandige eenheid. In feite is het gewoon een DLL met een bepaalde interface naar buiten. En een DLL is gewoon een apart soort executable. Een ActiveX control heeft dus een grote samenhang intern, maar het zal juist de koppeling naar buiten (andere ActiveX controls of gewone toepassingen) zijn die voor problemen kan zorgen. Waarom, zult u vragen? Welnu, denk eens een de TTable component van Delphi. Deze komt eigenlijk pas echt tot zijn nut als we deze gaan koppelen aan zogenaamde data-aware controls, zoals een TDBGrid or een TNavigator. En voor deze koppeling is een TDataSource component nodig. De koppeling tussen de TTable en TDataSource en de data-aware controls is behoorlijk sterk, en alhoewel Delphi 3 ons nu in staat stelt om VCL components in principe direkt om te zetten in ActiveX controls, zullen we toch problemen ondervinden om een TTableActiveX via een TDataSourceActiveX met een TDBGridActiveX te laten praten. Het gejuich verstomt al een beetje. Kunnen we toch niet met Delphi die mooie ActiveX controls maken om die vervolgens in andere omgevingen te gebruiken? Zijn we dan beperkt tot TWinControl en afgeleide components? Ja, eigenlijk wel. Maar er is nog hoop, want Delphi 3 kent ook.... de ActiveForm!

ActiveForm
Een ActiveForm is in feite een verzameling "normale" VCL controls die tezamen een ActiveX control vormen; een soort ActiveX container dus (alhoewel container in de OLE-wereld ook een beladen term is), en aangezien de "vorm" waarin dit alles plaatsvindt een "form" is, heet het eindresultaat dus passend ActiveForm, inderdaad. Dit betekent dus inderdaad dat we op een ActiveForm een normale TTable, TDataSource, TDBGrid en een TNavigator kunnen plaatsen, en toch uiteindelijk een ActiveX module hebben waarbinnen de VCL controls de sterke koppeling nodig hebben om ze op correcte wijze te laten werken. Dit principe verhoogt natuurlijk de modularisatie van onze toepassingen, aangezien we nu - in theorie - ActiveForms kunnen schrijven in Delphi 3 en die door omgeving X kunnen laten gebruiken, waarbij alleen het interface naar buiten van belang is (niet dat het interface van binnen niet belangrijk is, maar dat kunnen we intern testen). Tot zover de theorie. Laten we eens proberen om daadwerkelijk een ActiveForm te maken en te gebruiken.

Nieuwe ActiveForms
Voor het maken van een nieuwe ActiveForm moeten we eerst het huidige project afsluiten (een ActiveForm zit namelijk in een ActiveX library project, en niet in het standaard Delphi project). Kies vervolgens File | New uit het Delphi 3 menu en selecteer de ActiveForm icoon uit de ActiveX pagina als volgt:

object repository - activex

Hierna zal de ActiveForm Wizard getoond worden, waarin we de details van de nieuwe ActiveForm kunnen opgeven, zoals de nieuwe ActiveX naam, de naam van de implementatie unit en project ,en enkele speciale eigenschappen zoals de About Box, het gebruik van Versie Informatie en een Design-Time Licentie (in een .LIC bestand).

activeform wizard

Als we nu op OK klikken, zal Delphi 3 een nieuw ActiveX project aanmaken, met daarin de AboutBox en onze eerste ActiveForm. Als we in de editor de gegenereerde source code nader bekijken blijkt pas hoeveel er eigenlijk al achter de schermen is gebeurt. Delphi 3 heeft al een paar honderd regels code gegenereerd voor ons (waar we gelukkig weinig direkt mee te maken krijgen).
Het SDGN.dpr hoofd project bestand is echter in feite gewoon een library, die na compileren de extentie .ocx zal krijgen (zie de nieuwe compiler optie {$e ocx} die hiervoor bedoeld is).

  library SDGN;
  uses
    ComServ,
    SDGN_TLB in 'SDGN_TLB.pas',
    AxForm in 'AxForm.pas' {TDrBobActiveX: TActiveForm}
                           {TDrBobActiveX: CoClass},
    About1 in 'About1.pas' {TDrBobActiveXAbout};

  exports
    DllGetClassObject,
    DllCanUnloadNow,
    DllRegisterServer,
    DllUnregisterServer;

  {$R *.TLB}

  {$R *.RES}

  {$E ocx}

  begin
  end.
De algemene regel bij door Delphi gegenereerde code is: raak niets aan, tenzij je erg zeker van jezelf bent (en bereid opnieuw te beginnen). Dit geldt dus zowel voor de reeds gegenereerde code binnen de unit AxForm als de code voor het SDGN project (waarin de vier ActiveForm APIs worden gepubliceerd).
Gelukkig hoeven we ons ook helemaal niet druk te maken over al deze gegenereerde code, maar kunnen we ons rustig concentreren op datgene waar Delphi goed in is: RAD ontwikkeling. We kunnen het gegenereerde ActiveForm gewoon als een normaal Form behandelen, en er een klein database systeempje op ontwikkelen. Allereest moeten we er een TTable en een TDataSource component op laten vallen. De DataSource1 koppelen we aan de Table1 (property DataSet), en Table1 laten we naar de FISHFACT.DB tabel wijzen uit de DBDEMOS alias. Zet de Active property van Table1 op True om de tabel te openen en data beschikbaar te krijgen.
De snelste manier om nu ook de velden uit de tabel op het form te krijgen is door te dubbel-klikken op de TTable component, waarna we de Fields Editor te zien krijgen. Klik nu met de rechter muisknop binnen deze Fields Editor, en selecteer de "Add fields..." optie om de Add Fields dialog te krijgen met de acht mogelijke velden die bekend zijn in deze tabel. Elk van deze velden kan door drag&drop uit de Fields Editor gesleept worden op op het form gedropt worden. Op deze manier kan op snelle wijze het volgende form getekend worden:

drbobactivex tijdens design-time

Is het iemand opgevallen dat we nog geen regel code hebben geschreven? Alles is tot nu toe nog met de muis gebeurd (en als we de default namen voor de ActiveForm hadden gebruikt zouden we het toetsenbord zelfs helemaal niet meer nodig hebben gehad).
Gelukkig weten we wel dat dit geen gewoon form is maar een ActiveForm, en dat merken we dan ook meteen als we het project compileren of proberen te runnen. Na compileren krijgen we een bestand SDGN.ocx, en meteen ook de melding dat we deze dynamic link library (ActiveX) niet kunnen draaien zonder host toepassing.

Packages
Het compileren resulteert overigens in een SDGN.ocx van ruim 500 Kbytes, terwijl we geen een regel source code zelf hebben geschreven. Gelukkig is Delphi 3 ook uitgerust met packages; een soort van run-time DLLs die onderdelen van de Visual Component Library bevatten zodat die uit de executables gehaald kan worden. Als we de SDGN.ocx "met packages" willen compileren moeten we naar de Project Options dialog, en daarbinnen naar de Packages tab gaan:

project options - packages

Hier kunnen we aangeven dat we inderdaad met runtime packages willen compileren, en we kunnen zelfs aangeven welke packages we dan hierbij willen laten gebruiken. In dit geval VCL30 (met de standaard componenten) en VCLDB30 (met de database componenten). In praktijk is het natuurlijk zinloos om alle packages hier aan te geven, omdat dat slechts onnodig tot het nodig hebben van extra packages leidt.
Hercompileren van SDGN leidt in dit geval tot een nieuwe SDGN.ocx van slechts 38Kb (terwijl het origineel meer dan 500Kb was). Kijk, dat is nou wat ik besparingen noem!
We moeten nu natuurlijk wel zorgen dat ook de VCL30 en VCLDB30 runtime packages aanwezig zijn bij de nieuwe SDGN.ocx, en deze twee runtime packages zijn resp. 1.277.888 en 627.160 bytes groot. Hmm, dat is dus bijna 2 Mb extra om een besparing van 500 Kb mogelijk te maken. Toch niet zo handig als op het eerste gezicht leek? We moeten echter niet vergeten dat we in praktijk waarschijnlijk wel meer dan een toepassing schrijven die van packages gebruik maakt, en de packages hoeven natuurlijk (gelukkig) maar eenmalig opgehaald te worden. Bij een toepassing of drie loop je al aardig quite, en vanaf vijf of meer toepassingen die packages gebruiken ben je aantoonbaar in het voordeel bezig. Bovendien kunnen packages en applicaties vanuit Delphi gecompressed worden als een Microsoft cabinet (CAB-file): dit resulteert nog eens in een bestand dat slechts een derde zo groot is als het origineel...
Een ander voordeel van het gebruik van packages is het feit dat - als iedere client eenmaal de benodigde packages heeft - dan zullen updates van systemen veel sneller gaan dan vroeger, omdat de systemen een stuk kleiner zijn vergeleken met de tijd toen alles er nog in zat.

Web Deployment
Laten we eens kijken hoeveel moeite het kost om deze ActiveForm te gebruiken vanuit de Microsoft Internet Explorer 3.0 web browser. Hiervoor zullen we eerst de WEb Deployment Options (in het Project menu) moeten bepalen:

web deployment options - project

Het plaatje van figuur 5 is wellicht niet geheel duidelijk (en de handleiding is dat ook niet helemaal), dus let maar even op: de Target dir moet het volledige padnaam bevatten van de directory op de web server (of local intranet fileserver) waar de ActiveX naartoe gekopieerd zal worden. Als we al direktop een Web Server werken dan kan dit een lokaal pad zijn, zoals d:\www\drbob42\ActiveX.
De Target URL moet de URL (zonder filename) bevattten om bij het bovenstaande padnaam te kunnen komen, oftewel http://www.drbob42.com/ActiveX. Deze waarde wordt gebruikt voor de codebase van de OBJECT tag in de gegenereerde .htm file. Dit veld kunnen we niet leeg laten (bijvoorbeeld als de OCX in dezelfde directory staat als het gegenereerde HTM bestand), maar wel kunnen we "./" gebruiken voor gewenste effect.
Tot slot dient de HTML dir het volledige padnaam te bevatten van de directory, lokaal of op de webserver, waar we onze HTM pagina willen laten genereren. Ik plaats deze meestal in dezelfde directory als de ActiveForm, zodat ik bij het vorige veld dan inderdaad de waarde "./" moet invullen.
De beschikbare opties bieden nog te mogelijkheid tot CAB file-compressie waardoor de bestanden gecomprimeerd zullen worden. Comprimeren duurt even, maar decompressie is relatief snel. Code signing is een andere optie is erg handig is als we de ActiveForm ook door anderen willen laten gebruiken. Zoals ik tijdens een presentatie van de SDGN al eens heb laten zien, is een ActiveX control gewoon een toepassing die draait op de machine van de gebruiker. Dus niet alleen binnen de wereld van bijvoorbeeld Internet Explorer, maar binnen de wereld van de machine en de bevoegdheden van de gebruiker (bijvoorbeeld 'administrator' op het netwerk). En een ActiveForm kan binnen deze bevoegdheden doen wat hij wil. De harddisk formateren, bijvoorbeeld, of schade aanrichten aan het netwerk. Of andere stiekeme dingen doen. Aangezien een ActiveX in feite een black-box is (we kunnen niet zien wat er binnen gebeurt) zijn ze dus in principe onveilig in gebruik. Met name als ze van het internet af komen, waar ze verborgen in een HTML pagina hun werk kunnen doen (het is haast nog erger dan een virus). Code Signing is een manier om de zaak een klein beetje onder controle te houden: een Code Signing licentie (zie http://www.VeriSign.com; momenteel nogal moeilijk te krijgen voor Europese ontwikkelaars) zegt in feite iets over de betrouwbaarheid van de auteur van de ActiveX. Niet over de ActiveX zelf. Het blijft dus een zaak van vertrouwen. In een internet omgeving heb ik dat vaak niet, op het intranet wel, maar dan alleen voor die ActiveForms waarvoor men de moeite heeft genomen ze met Code Signing te beveiligen. Meer hierover later.

De tweede pagina van de Web Deployment Options dialog bevat de opties voor de twee run-time packages die nodig zijn voor onze ActiveForm. Op de plaats kunnen we de plaats aangeven waar deze packages moeten komen.

web deployment options - packages

Nadat we ook deze dialog hebben ingevuld kunnen we naar de Project Options dialog gaan om tot slot de versie informatie in te vullen (dit is noodzakelijk om bijvoorbeeld tools als Internet Explorer ervan te overtuigen dat een ActiveForm daadwerkelijk gewijzigd is tussen twee releases):

project options - versioninfo

Na deze dialoog kunnen we eindelijk de menu-keuze Project | Web Deploy aanroepen, die de SDGN.ocx compressed, naar de juiste directory kopieert, en de bijbehorende HTML en INF bestanden genereert. Het compressen kost een paar seconden:

deploying sdgn.ocx

Het resultaat bestaat uit een vijftal bestanden: SDGN.inf, SDGN.htm, SDGN.can, VCL30.cab en VCLDB30.cab. We weten inmiddels wat CAB-files zijn, en SDGN.inf is een bestand in Windows INI-file formaat dat de informatie bevat voor bijvoorbeeld Internet Explorer, over de ActiveForm en de benodigde packages. De inhoud is als volgt:

  ;Delphi-generated INF file for SDGN.ocx
  [Add.Code]
  SDGN.ocx=SDGN.ocx
  VCLDB30.dpl=VCLDB30.dpl
  VCL30.dpl=VCL30.dpl

  [SDGN.ocx]
  file=SDGN.cab
  clsid={D0105723-DAD7-11D0-B848-444553540000}
  RegisterServer=yes
  FileVersion=1,0,42,0

  [VCLDB30.dpl]
  file=
  FileVersion=3,0,5,54
  DestDir=11

  [VCL30.dpl]
  file=http://www.borland.com/vcl30.cab
  FileVersion=3,0,5,53
  DestDir=11
Voor de VCL30 package kon ik al meteen gebruik maken van de package die op de Borland website staat, dat scheelt natuurlijk weer in het uploaden naar mijn eigen website. Ook de versieinformatie en de CLSID en filenaam voor de eigenlijke ActiveForm SDGN.cab is aanwezig.
Het laatste bestand, de SDGN.htm bevat de gegenereerde HTML testpagina, en die ziet er als volgt uit:
  <HTML>
  <H1> Delphi ActiveX Test Page </H1>
  You should see your Delphi forms or controls embedded in the form below.
  <HR><center>
  <OBJECT
    classid="clsid:D0105723-DAD7-11D0-B848-444553540000"
    codebase="SDGN.inf"
    width=350
    height=250
    align=center
    hspace=0
    vspace=0>
  </OBJECT>
  </HTML>
De <OBJECT> tag vertelt de web browser dat er een (ActiveX) object volgt. Netscape Navigator ondersteunt helaas geen ActiveX controls zonder plug-in (en conversie van de OBJECT-tag), maar met Internet Explorer werkt dit prima. De codebase wijst naar het SDGN.inf bestand dat we net zagen, en dat de gedetailleerde informatie bevat over de ActiveForm en de benodigde runtime packages. Het enige aspect aan de gegenereerde HTML waar ik absoluut niet van begrijp waarom het erin staat zijn de WIDTH=350 en HEIGHT=250 waarden. Deze slaan dus echt absoluut nergens op, en leiden zelfs tot een ActiveForm die niet geheel wordt afgebeeld (zie figuur 10-A). Gooi deze twee regels gewoon weg of vervang ze door de echte breedte en hoogte van de ActiveForm, maar dit is grote onzin.
Nu alle bestanden hun plekje gevonden hebben, kunnen we eindelijk Internet Explorer 3 gaan opstarten om te kijken of het ook echt werkt zoals we verwachten...

Internet Explorer 3
Van Microsoft Internet Explorer 3.0 - te vinden op de Delphi 3 CD-ROM - moet eerst de securrty goed worden ingesteld door naar de View | Options Security dialog te gaan en de security level op high of medium te zetten. Een setting van "high" zorgt ervoor dat alle niet-gecertificeerde (code signed) ActiveX controls meteen genegeerd worden, terwijl een setting van "medium" zorgt voor een vraag of we wel zeker weten dat we de betreffende control willen "uitvoeren". Voor ontwikkelaars is "medium" aan te raden. Zet de security nooit op lager dan "medium", want dan nodig je alle ActiveX controls uit om vrolijk aan de slag te gaan (ook op het internet) en dat is natuurlijk vragen om moeilijkheden...

internet explorer

Met de security setting op "medium" zal onze SDGN.ocx ActiveForm - die geen code signing heeft - voor een warning zorgen, zie bovenstaand figuur. Als we op Yes klikken zal de ActiveX control gedownload worden, in de \WINDOWS\OCCACHE subdirectory geplaatst worden, geregistreerd worden als ActiveX control, en tenslotte geladen worden en "uitgevoerd" binnen het vooraf gedefinieerde frame van Internet Explorer (weet je nog de height en width setting in het HTML-bestand?)

drbobactivex in internet explorer

Als om wat voor reden dan ook iets misgaat tijdens het downloaden, registreren of uitvoeren, dan krijgen we in plaats van de mooie ActiveForm een klein rood kruisje te zien. De "red cross of death" ook wel genoemd.
Als we de HEIGHT en WIDTH statements uit SDGN.htm weghalen, komt de ActiveForm pas goed te voorschijn:

drbobactivex in internet explorer

En hier issie dan: onze eerste ActiveForm, met database connectivity etc. Natuurlijk moet de Borland Database Engine (BDE) op de client machine aanwezig zijn, net als de voorbeeld database, om echt te kunnen werken. Indien de ActiveForm met een database op de web server wil praten zullen we bijvoorbeeld van MIDAS gebruik moeten maken.
Mocht iemand nog vragen, opmerkingen of suggesties hebben, dan hoor ik die het liefst via .


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