Developing components in DelphiLast Updated: 9/21/2008 | |||||||||||
| Sections above here: Home » Development » Custom Components | |||||||||||
|
Sections below here: Topics in this section: |
Delphi component development is simple, but there is one thing you should bear in mind here. It was mentioned before that IW "wraps up" all its code into HTML tags. Hence the set of visual components you can develop in IntraWeb is restricted by
It could make you think in terms of HTML tags rather than pure Delphi code. InheritanceTIWCustomControl is base class to inherit your own component from - if you want to design one from the scratch. There are also "custom skeletons" available. E.g. TIWCustomLabel, these base classes already define quite a few base behavior and make your life easier. Being the base classes, you should never create instances of them directly. Descendant classes should be used instead to override or introduce properties, methods etc. You can also descend from "final" component classes, such as TIWLabel. It basically depends on what you want to achieve. The more different your new component is supposed to behave, the earlier you have to descend. [TIWCustomControl] -> [TIWCustomLabel] -> [TIWLabel] "Moving Label" demoTo illustrate, let's develop a moving label. It will be inherited from TIWCustomLabel.
The purpose of this component is to show a moving advertisement text running through the browser
window. The HTML-tag which the new component is based upon is "marquee". This simple demo will show the core ideas of IntraWeb components. To begin with, launch Delphi's New Component wizard and fill the gaps as follows:
The new class name is TIWMovingLabel, inherited from TIWCustomLabel. After clicking on "Finish" you should have the following unit: unit IWMovingLabel; Further, we have to let IntraWeb HTML-render machine know about HTML tags the new component should be wrapped up into. To do this let's declare override procedure RenderHTML as
type TIWLabelM = class (TIWCustomLabel) private { Private declarations } protected { Protected declarations } public function RenderHTML: TIWHTMLTag; override ; published property Caption; end ; with following constructor
constructor TIWLabelM.Create(AOwner: TComponent); begin inherited Create(AOwner); Caption:=Name; end ; And finally, write its new implementation
function TIWLabelM.RenderHTML: TIWHTMLTag; begin Result:=TIWHTMLTag.CreateTag(' marquee '); try Result.Contents.AddText(Caption); except FreeAndNil(Result); raise ; end ; end ; The passage above is the gist of the whole topic. The only thing remains unrevealed is the TIWHTMLTag class . You can get to know more on TIWHTMLTag class from Help or refer to Tags implementation
Installing components on Delphi's Component paletteInstalling a new IW component on Delphi Component palette is done in the usual manner, but there is one thing here to point out. When you place the IWLabelM on a form in design time no caption shows. It looks like Use the resource icon we made in Delphi's Image Editor tool and without any captions. Some extra code must be added to paint a text:
initialization IWRegisterPaintHandler('TIWLabelM',TIWLabelMPaintHandler);
uses SysUtils, Classes, IWBaseControl, IWControl, IWCompLabel, {$IFDEF Linux}QGraphics, {$ELSE}Graphics, {$ENDIF} {$IFDEF Linux}QControls, {$ELSE}Controls, {$ENDIF} IWHTMLTag, IWTypes,IWDsnPaint,Types;
TIWLabelMPaintHandler = class (TIWPaintHandlerDsn) public procedure Paint; override ; end ;
procedure TIWLabelMPaintHandler.Paint; var TheRect : TRect; begin with FControl as TIWCustomLabel do begin TheRect:=Rect(2,2,Width-2,Height-2); Canvas.TextRect(TheRect,2,2,Caption) end ; end ; All this stuff above will result in true "Delphi-style" component design-time appearance. Testing the installed componentWhen testing the TIWLabelM we could see the advertising text travel ing from right to left on the screen: T he corresponding HTML source looks like: <marquee id="TIWLABELM1" class="TIWLABELM1CSS">Text to move</marquee> TIWHTMLTagIt allows the developer to work with HTML-tags and holds tag information for most of the IntraWeb controls. TIWHTMLTag is extensively used by IntraWeb to build HTML tags for the final pages, hold parameter information, JavaScript events, etc. We'll just concentrate on few of its members.
JavascriptEmbedding into componentsYou may put JavaScript code directly into component to be rendered. It makes your application more flexible then you assign values to ScriptEvents or to TIWForm.JavaScript. Let's extend "Moving Label" example in the following way: we need the IWLabelM to show various advertising text in series. TIWControl.AddToJavaScriptOnce You could re-implement TIWLabelM as follows: function TIWLabelM.RenderHTML: TIWHTMLTag; var LScript : string ; LTag : TIWHTMLTag; begin Result:=TIWHTMLTag.CreateTag('marquee'); try Result.Contents.AddText(Caption); Result.AddStringParam('loop','1'); Result.Add('onfinish=ff()'); LScript:= ' function ff() { '+ ' var o = event.srcElement; '+ ' o.stop; ' + ' o.innerHTML = "Other adverti s ing text"; '+ ' o.start; }'; AddToJavaScriptOnce(LScript); except FreeAndNil(Result); raise ; end ; end ; AddToJavaScriptOnce method (it comes from TIWLabelM parent ) adds JS-code of ff() function into result page. When "onfinish" event occurs, another text starts to move through the browser window. Developing custom JS libsEmbedding JS code into a component has a major shortcoming. When you instantiate TIWLabelM twice or several times it leads to several ff() declarations in result page. Each instance will have its own ff() function with almost the same code. To avoid duplications and make your project faster you can use custom JavaScript libraries. IntraWeb itself based upon a number of them: · IWCL.js. This is core library that supports align/anchors functionality. · IWCSData.js. This is used for client side datasets. Supports client side data objects. · IWExplorer.js. Supports client side browser for HTML elements searching, etc.· IWCommon.js. This is the common JS code for all supported browsers. Developing custom JS libraryTo develope custom JS library for our example do the follows: 1. Create text file as function ff() { var o = event.srcElement; o.stop; o.innerHTML = " Other adverti s ing text "; o.start; } 2. Save it into the project's directory as IWLabelM.js 3 . Create resource file containing the following tab-separated data IW_JS_IWLABELM RCDATA "IWLabelM.js" and save it with the name IWLabelM.rc. Note : RCDATA means binary resource type. IW_JS prefix means it contains JS code only. Note : Be sure you write it in upper case. 4. Compile resource file: >brcc32.exe IWLabelM.rc It makes the resource file IWLabelM.RES ready to be included into the component unit. Including the resource into the component's source
Make sure you include the resource as follows: unit IWLabelM; .... implementation{$R IWLabelM.RES} Then add it to the internal files list using initialization section of IWLabelM unit. After doing this the section should read as: initializationIWRegisterPaintHandler('TIWLabelM',TIWLabelMPaintHandler); TIWServer.AddInternalFile('IW_JS_IWLABELM', '/js/IWLabelM.js'); Adding script file into the page produced
To add the script file into the current context rewrite the RenderHTML implementation as below: function TIWLabelM.RenderHTML: TIWHTMLTag; begin Result:=TIWHTMLTag.CreateTag('marquee'); try Result.Contents.AddText(Caption); Result.Add('onfinish=ff()'); Result.Add('loop=1'); AddScriptFile('/js/IWLabelM.js'); except FreeAndNil(Result); raise ; end ; end ; The TIWLabelM.AddScriptFile comes from custom parent component and performs the JavaScript non-duplicated code including we are after. The core server will spit out the result HTML-code as follows: ... <meta name="GENERATOR" content="IW5.1.22 Serial 12334567"> <script language=Javascript src="/js/IWCommon.js_5.1.22"></script> <script language=Javascript src="/js/IWCL.js_5.1.22"></script> <script language=Javascript src="/js/IWCSData.js_5.1.22"></script> <script language=Javascript src="/js/IWExplorer.js_5.1.22"></script> <script language=Javascript src="/js/IWLabelM.js_5.1.22"> </script> </head>... JavaScript event handlingTo handle client-side event you may use ScriptEvents property. But it is a good practice for component developers to use TIWControl.HookEvents instead. Let's override HookEvents and redeclare TIWLabelM as follows: type TIWLabelM = class (TIWCustomLabel) private { Private declarations } protected { Protected declarations } public { Public declarations } constructor Create(AOwner: TComponent); override ; function RenderHTML: TIWHTMLTag; override ; procedure HookEvents(AScriptEvents: TIWScriptEvents); override ; published property Caption; property OnClick; { Published declarations } end ; HookEvents comes from TIWControl and allow the programmer to assign any code for AScriptEvents handling . If we need, for example, the Moving label to stop when click a mouse button on it, we may fill our event handler with: procedure TIWLabelM.HookEvents(AScriptEvents: TIWScriptEvents); begin AScriptEvents.HookEvent ('OnClick', //<-the JS event name 'document.all["'+HTMLName+'"].stop();' //<-JavaScript code itself ) end ; HTMLName is the name of TIWLabelM instance which OnClick event is to be handled. Note. IntraWeb adds the function result into the outcome page as return true; by default. You may define your own return value if it is necessary: AScriptEvents.HookEvent ('OnClick', 'document.all["'+HTMLName+'"].stop();'+EOL+ 'return false;' ); | ||||||||||
(C) 2002-2009 - Atozed Software Ltd. | |||||||||||