Está en la página 1de 52

IntraWeb Tutorial - User Input

In this tutorial you'll learn how to use multiple forms, how to handle user input and how to use sessions. In order to understand and run the example in this tutorial you should read the "Hello World" tutorial first.

What is Next
This application is built using IntraWeb's application mode. The last tutorial was very basic and designed to simply show you how easy it is to get an IntraWeb application up and running. As you will soon see the code used is still standard Delphi code. We challenge you to try even something this simple with any other web development tool. Other development tools require you to set up adaptors, bindings, or handle the HTTP variables your self. Not IntraWeb, IntraWeb is truly componentized. For this demo, we will continue by modifiying our "Hello World" application built in the Hello World demo. If you have not created this project yet, you will need it for this demo.

Changes to the Main Form

Set the form's Title property to "What is your name?". This will be displayed as the page title when shown in the browser. Change the label's Caption to read "What is your name?" Add a TIWEdit to the form. Set the Text property to be blank. Set the Name property to editName. Add a TIWButton to the form. Set the Caption property to "Talk to me!".

Your form should now look something like this: New Main Form

Handling a Button Click If you have never worked with web development tools before, this next step will not seem like magic for you as you will think, "This is the way it should work, no?". However if you have worked with other web development tools, you will now really begin to see where IntraWeb is different. To handle a button click in IntraWeb, it is just like a normal Delphi application. Simply create a OnClick event for your button and add code. To do this, double click on the button. Delphi will create a shell event for you similar to this:

Add the following code to the event:

Testing the Application Run the application as we did in the previous demo, and press F9 again after the debug window appears to launch the browser. The browser should appear like this:

In Internet Explorer

Notice the browser has picked up on the page title as set in the form's title property. Enter your name in the edit box and press the button. The browser will respond like this:

Hello !

Special Notes
Netscape Users Please see "Why when debugging using the IDE and Netscape 4 is the application is slow on the development machine and the task manager shows 100%?" in the FAQ. Internet Explorer Users Please see "When when using Internet Explorer is there a delay when I first click on a button?" in the FAQ. Farmers Please see "Why did the chicken cross the road?" in the FAQ.

Code Examination
Wow! That was pretty cool eh? Yes, but the really cool part was that it was done purely with standard Delphi code. We still have not written a single line of HTML or Javascript, and this is exactly how IntraWeb works. Let's take a look again at the code we wrote to do this and examine it line by line.

Wi sc ot Ed OW ds wd al ce bo tf hi Ttn /no O n a i l hr t e u

f n e o /

Multiple Forms ust to show you that there are no hidden gotchas with IntraWeb, let's continue on and show you how easy it is to do multiple forms with IntraWeb. Select New | Other from the File menu, and select the IntraWeb tab. This time select New Form and click OK: Creating a New IntraWeb Form

The following dialog will appear, allowing you to select the form type:

New Form Wizard

This dialog allows you to select whether you want a Page Mode form, or an Application Mode form. For each of those, the HTML type is also selectable, so you can chose to produce a HTML 3.2 form or a HTML 4.0 form. For this tutorial we'll chose "Application Form", which will produce a HTML 4.0 application mode form. For a detailed explanation of page mode and application mode, please refer

to the IntraWeb Manual. You will now have a new blank form again: New Blank Form

Using the property inspector, apply the following changes: Change the form Name property to formHello. Add a TIWLabel Set the Name property to lablHello. For the Font property: Bold = True Size = 24 Name = Arial Narrow Color = clRed

AutoSize = False. We will be adjusting the text at run time and thus will be manually

adjusting the width. Width = 300 Add a TIWLink Set the Caption property to Close. Create an OnClick event by double clicking on the TIWLink. Add the following statement to the event:

Your form should now look something like this:

Now let's move back to our main form. Change the button click event to read as follows:

Let's also add one more TIWButton to the main form. Set its caption to Done, and create an OnClick event to read:

Now run the application and press F9 when the debug window appears. The browser should appear similar to this:

Enter your name and click the Talk to Me! button. The browser now displays your second form like this:

Notice that even the browser caption has been updated with your name. Click the Close link. The browser will return to your main form:

Now click the Done button. The browser will terminate the application and display this message:

Wow! Multiple forms, transparent user input, automatic session management, the works! And we still have not written a single line of HTML or Javascript. Does it get better? Yes it does, but you will need to see for yourself by trying IntraWeb.

Code Examination

Faster Web Development If you are a Delphi shop, there is no doubt your programmers can be up and running with IntraWeb in a matter of minutes while continuing to use their existing skills. You can develop web applications in days instead of months, and you can take on web projects previously deemed impossible or too time consuming. Now, can you honestly say that about any other web development tool? Conclusion This tutorial took the next step and demonstrated the ease of handling user input and managing multiple forms.However IntraWeb is far more powerful and has many more features than what has been demonstrated here. To see the full power of IntraWeb you need to look at the included demos and better yet, write your own application.

IntraWeb Tutorial - Implementing a "Hello World" application

Author: Atozed Software Homepage:

Hello and welcome to the exciting world of IntraWeb. In this tutorial you'll see in a few simple steps how to create and execute an IntraWeb application

To run the example in this tutorial you'll need the following: IntraWeb 5.1 in Application Mode (to get an evaluation copy of IntraWeb, please go to the Atozed Software website - One of the following : Delphi (5, 6 or 7), Kylix (2 or 3), C++ Builder (5 or 6) or JBuilder. Visual Studio.NET is currently under development Approximately 20 minutes of your time (installation time not included)

Creating a new application

his application is built using IntraWeb Borland Edition and application mode.

The first step is to create a new IntraWeb application. To do this select the File menu, then New (Select New, not New Application, etc), then Other. A "New Items" dialog will appear. Select the "IntraWeb" tab. It should look like this:

IntraWeb New Dialog

Using this dialog you can start a new IntraWeb application or add new IntraWeb forms to your existing applications. After selecting "IntraWeb Application Wizard", the wizard will launch and you'll be presented with the following dialog:

The IntraWeb Application Wizard

For this application we'll select "StandAlone Application". This will produce a self contained executable, that will be the only thing on the server side that you'll need to run your application. You do not need a web server of any kind. Notice the other available options: you could make your application a Windows service, and ISAPI extensions for web servers that support ISAPI, like IIS and OmniHTTPD, and even an Apache module. The options in the right panel specify whether the application should have a DataModule by default, if support for user sessions will be available, whether the HTML output should be 3.2 or 4.0 (default is 4.0 unless you check the "Create Main form as 3.2" box) and if the ISAPIThreadPool unit should be used (for the IIS server only). Each new IntraWeb application consists of three modules: 1. Project1.dpr - This is the project file. 2. Unit1.pas and IWUnit.dfm - This is the main form of your application. You can change this by editing the project file, or even have multiple main forms determined by an incoming HTTP variable. 3. ServerController.pas and ServerController.dfm - This is the server controller and used to configure your IntraWeb application and create application level events. In a new application you can leave all properties as default. If you want, you can rename any of the files by doing a Save As from the File menu.

Implementing "Hello World"

If you have worked with other web technologies you are probably gearing up for a very big tutorial on simply how to implement even the simplistic "Hello World". I hope we will not disappoint you, but this tutorial will be very short, but only because IntraWeb makes this so amazingly simple. Open the main form of the application (Unit1). It will appear as a blank form like this: Blank IntraWeb Form

You will quickly notice the form is blank. Do not worry - this is just like a new normal Delphi application when we create it. The main form is blank and we must implement our application. Select the IntraWeb standard components tab (IW Standard tab) on the component palette as shown here:

IntraWeb Standard Palette

In the standard palette you'll see the base components for web development. However, that's not all. You an look in the other IntraWeb palettes to see components for database access, HTML 3.2 output, client side processing etc. For a complete reference of IntraWeb components, please see the IntraWeb Reference file. You can download this file from the Atozed Software website. Select the TIWLabel and then place it on the form. It should look something like this:

Main form with label

Now just like a normal Delphi application use the property inspector to change the caption of the label. Change the caption to "Hello World Wide Web!". You will notice that the label on the form updates itself to reflect this change:

Caption of the label has changed

Now all that is left to do is to run the application and test it.
Running the application

We have created this application as a stand alone application. What this means is that it will execute completely stand alone and become its own web server. This is extremely useful for debugging and testing, but it can also be deployed in this manner. Not only can it run stand alone, but it can be installed as a service on Windows NT, Windows 2000 and Windows XP. Please see the IntraWeb documentation for more information on this. To test our application, simply run it as you would any other Delphi application. You will then see a dialog similar to this:

IntraWeb Stand Alone Information Dialog

This is a dialog to assist you in testing and debugging. To test it in the browser click Run then Execute or press the F9 key. This will launch your default browser with the start URL for the application:

The browser window


Congratulations! You have just created a web application! All of this with no HTML, and it was just like a normal Delphi application was it not? Now you might say "Well that is fine and dandy, but what about input? You are just showing us limited pieces and there are hidden gotchas." Trust me, there are no such "gotchas" waiting for you. IntraWeb handles input just like any other Delphi application. Want to handle a button? Define the OnClick event, that is it. Want to read the value of a text box? Read its text property.

"IntraWeb: A New Way to the Web" by Cary Jensen

Abstract: IntraWeb is a framework and component set that permits you to quickly and easily build interactive Web sites using Delphi, Kylix, C++ Builder, and JBuilder, and it may very well change the way you develop Web applications from now on. IntraWeb is a component-based Web development framework written in Delphi by AtoZed Software. It combines the visual development normally associated with Borland's RAD tools with a robust collection of dynamic Web site creation features. Better yet, it is included in the

latest versions of Borland's premiere RAD development tool: Delphi 7 Studio, and is available for Delphi 5 and 6, Kylix 2 and 3, C++ Builder 5 and 6, and JBuilder 7. For those of you who are following my The Professional Developer soapbox, you already know that I am in the midst of an extensive series of ClientDataSet articles. That series will continue, as I have many more installments in the works, including discussions of nested datasets, options for applying updates, using parameterized queries, passing data between the ClientDataSet and its DataSetProvider, and much more. But for now, I want to take a quick break and talk a little about IntraWeb. Why? Because it is fantastic. It is a rare thing when you come across a framework so flexible, so powerful, and so consistent with the "culture of excellence" that is the hallmark of Borland's own software. But IntraWeb is the real thing. If you have not tried it yet, don't wait. It is definitely worth a serious look. So, that cat is out of the bag. I am a big fan. You may already be a fan, too. But if you haven't yet had a chance to look at it, read on. IntraWeb is Web development done right. While it is not appropriate for every dynamic Web site, it more than meets the needs of a great number of developers. And does so in a style that is elegant, extensible, and downright fun. Let's begin at the beginning. IntraWeb supports two distinct styles of Web site development: application mode and page mode. In application mode, the IntraWeb application is a selfcontained, state-maintaining executable that generates HTML and JavaScript for rendering by a Web browser. IntraWeb applications designed around application mode can be designed as a Web server extension (such as an ISAPI DLL or an Apache module), or as a stand-alone executable. When designed as a Web server extension, IntraWeb applications are invoked through a running Web server. Specifically, the URI (uniform resource identifier) referenced by a Web browser will refer to a Web server, which in turn will pass control to the IntraWeb application. In this configuration, all requests are submitted to the Web server, and all responses are returned by the Web server. These responses, however, are generated entirely by the IntraWeb application (at the request of the Web server). This relationship is represented in the following diagram.

I must admit that this diagram is a little misleading, in that it fails to represent the multithreaded nature of the client/server interaction on the World Wide Web. To be more accurate, the IntraWeb DLL or Apache module on the right side of this diagram is executing in the context of a specific thread on the Web server. To put it another way, in almost every situation in which

IntraWeb components are generating their HTML, they are operating in a multithreaded environment. The only exception is when you are executing IntraWeb pages in page mode, but more about that later. In the stand-alone mode, the IntraWeb application is a server, listening for HTTP requests on a specified port. In this mode, the IntraWeb server processes the browser's HTTP requests directly. This relationship is represented in the following diagram.

Again, this diagram fails to capture the complexity of the IntraWeb environment. In these situations, the IntraWeb application is a multithreaded server, with each request from a particular browser window being handled by a different thread on the server. Now let's consider page mode. By comparison, in page mode IntraWeb is used to define individual pages of the Web site, but it does not take responsibility for all of then internal processing. In page mode, the primary processing is performed by a "bridge," which is simply a Web server extension. Currently, these Web server extensions can be created in Delphi, Kylix, or C++ Builder. In other words, when used in page mode, IntraWeb is used in conjunction with a Web server extension created either using Web Broker or WebSnap. In this configuration, the HTTP request is received by a Web server, which in turn passes the request to a Web server extension created in Web Broker or WebSnap. The Web Broker's ActionDispatcher or the WebSnap's PageDispatcher directs the request to one of its Web action items, or one of its Web page modules, respectively, based on the pathinfo portion of the URI. This Web action item or Web page module may produce a response using one of the normal Web Broker mechanisms. But when used with IntraWeb, the Web action item or the Web page module will call on an IWPageProducer to invoke an IWPageForm (a special form class declared in the IntraWeb framework) to produce the HTML and JavaScript that Web Broker or WebSnap returns to the Web server. The Web Broker Web module or the WebSnap Application Module will also include an IntraWeb IWModuleController, which is used when an IWPageForm generates HTML and JavaScript that can post an HTTP request intended for processing by the IWPageForm itself. This relationship is depicted in the following figure.

Like the earlier diagrams, this one also fails to capture the multithreaded nature of this interaction. In page mode, it is Web Broker or WebSnap that either spawns separate threads or is invoked on separate threads to respond to HTTP requests that it receives from a Web server. Unlike in IntraWeb's application mode, in page mode a given thread is not dedicated to a particular browser session or even necessarily to two different requests from the same browser. In application mode the IntraWeb server controller provides automatic state maintenance. Specifically, the first time the IntraWeb server processes a request from a particular browser window, it creates an object that is responsible for responding to that and all subsequent requests from that window. This object is often referred to as the session. I am being very particular about distinguishing between a browser window and a specific computer on the Internet. A user can open multiple browser windows simultaneously. When using IntraWeb, each of these browser windows is associated with a different session, which in turn maintains specific information about what the user is doing in that window. Like any other object you can define in an object-oriented language, this object can, and does, persist data, including any information that you want to maintain for the particular session that it is responsible for responding to. This information can include simple data, such as the time the session started, the number of pages viewed, and so forth. But it can also include more complicated data, including objects. For example, a particular session can have its own database connection, query result sets, current dataset records, just to name a few examples from the database realm. I f you want to maintain state in a page mode IntraWeb-based application, you must use one of the standard state maintenance techniques from either your Web Broker application, or from the IWPageForm that produces the response. These include inserting state information into HTML tags such as anchor <A> or image <IMG> tags (when those tag refer back to the Web Broker application), inserting hidden fields into HTML forms that will be returned to the server, or writing and reading cookies. These two IntraWeb modes, application and page, represent very different approaches to building dynamic Web sites. When using application mode, IntraWeb provides both state management as well as a significant amount of processing power. This processing power is in the form of standard component event handlers that you write, and which get executed on the server in response to things that occur on the browser. These features come at a price, however. Specifically, application mode Web sites tend to behave in well-defined ways, which

approximate the way most desktop applications operate. This behavior differs slightly from how most dynamic Web sites behave. For example, in an application mode IntraWeb application it is normally not possible for a user to use their browser's "back" button to return to a previous page (since that page was produced as the result of some processing). In this mode, if you want to permit a user to return to a particular page of your application mode Web site, you provide that feature through your Web site's interface, such as a button or link. When the user clicks that button or link, you produce a new page, which may essentially reproduce a previously viewed page. Not all versions of Delphi, Kylix, or C++ Builder support the deployment of both application mode and page mode applications. If you are using the Enterprise or Architect version, you can create both types of IntraWeb applications. Professional edition users can develop, but not deploy, application mode IntraWeb applications. Professional edition users must purchase an additional license from AtoZed Software ( to deploy application mode IntraWeb applications.

More About Application Mode

The distinction between application mode and page mode is very important, and it is worth repeating, with a slightly different perspective. In application mode, a browser is assigned a thread upon making its first HTTP request handled by IntraWeb, and that thread will stay alive to service that specific browser session only, until either the browser submits a call to terminate the thread, or the browser times out. A time out occurs when the browser fails to make another request of the IntraWeb application for a specified period of time. The timeout duration is configurable, and it is set to ten minutes by default. One consequence of this timeout approach is that, using the default settings, a user who simply closes their browser while viewing a page generated by an application mode IntraWeb application will leave a thread alive on the IntraWeb server until the timeout period expires. Fortunately, the thread created to handle each browser session is fairly lightweight, requiring about one kilobyte of memory per thread, prior to your customizations. Unless you make changes that significantly increase the amount of memory required for each thread (session), you can easily have hundreds or even thousands of these threads in memory at a time. That the browser session has thread affinity means that IntraWeb application mode applications are much more similar to typical client-side applications than most other interactive Web application frameworks. In a traditional client workstation application, there is one copy of the application running for each user. The user interface of that application provides the options that are available to the user, and when a user selects from a menu or clicks a button the application responds. The threads of an IntraWeb application are somewhat like the individual instances of a traditional Delphi GUI client. These threads display pages that you design, and the user uses the user interface of these pages to select what they want the application to do. When the user selects from a menu or clicks a button in an application mode IntraWeb page, the thread that produced that page responds. This is not how traditional Web server extensions, such as CGI or ISAPI Web server extensions work. Each request handled by a Web server extension is independent of every

other request. The CGI application must inspect data in each and every HTTP request that it receives (such as query string values, path info values, or posted input fields) in order to produce the next page. While application mode IntraWeb application do behave similar to traditional Windows applications in many respects, there is one big important difference. Specifically, IntraWeb applications are multithreaded by their nature. Consequently, if there is any data that you want to be able to share between the various threads, you must use thread synchronization techniques in order to access those resources. These include critical sections, thread lists, and multi read/exclusive write synchronizers.

Delphi Web Development Made Easy
IntraWeb is a set of VCL objects that extend the capabilities of Delphi so you can develop Web applications much as you would standard executables. Create Web forms, add components, write events, and your project is done. In brief, AToZed Software's IntraWeb allows true RAD Web development. IntraWeb installs smoothly. The process is automated and includes putting all components onto the Component palette and making necessary modifications to Delphi. A full installation requires about 7MB of disk space. The uninstall is just as clean, and removes all traces of IntraWeb from Delphi without any manual cleanup. I was impressed by IntraWeb's demos, but anyone can write good-looking demos. After all, demos are sales pitches, and we all know how much a sales pitch speaks about the actual product. I was genuinely amazed when I saw the source code to the demos, and began to understand why IntraWeb is so special. I was expecting to see HTML, JavaScript, Web modules, and state management, just as I would with WebSnap. What I saw instead was "normal" Delphi code - and that was all. If I hadn't seen it run in a Web browser first, I would have thought it was a normal Delphi application. I still wasn't convinced, however; there had to be a catch. So I built a demo similar to the one I am about to show you. I figured if I could write a Web application as easily as the demos made it look, then IntraWeb was for real.

Testing It Out
To create a new IntraWeb application, select File | New | Other | IntraWeb | Stand Alone Application. Stand-alone projects have an embedded HTTP server, and therefore don't need Internet Information Server, Apache, or any other Web server. Such projects are ideal for debugging, but they also can be installed as Windows services and deployed as they are. If a stand-alone project is run as an application (i.e. not as a service), a debugging interface will appear. This is similar to WebSnap's Web Application Debugger, but it's much simpler and more convenient to use. All IntraWeb projects start with two units: a blank application form (Web form) and a server controller. The server controller has properties for configuring session timeouts, ports, and so on. Once I had my main form, I created some basic controls so that my form looked like Figure 1.

Figure 1: The main form at design time.

Then I created the event shown in Figure 2 and assigned the OnClick event of both links to it. As you can see, it isn't very complicated. The point is that it's all Delphi code. This is the way all IntraWeb applications appear. So when the application is run, the debugging interface will appear (see Figure 3).
procedure TformMain.AddLinkClick(Sender: TObject); var i: Integer; Dest, Src: TIWListbox; begin if Sender = AddLink then begin Dest := ReserveList; Src := AvailableList; end else begin Src := ReserveList; Dest := AvailableList; end; for i := Src.Items.Count - 1 downto 0 do if Src.Selected[i] then begin Dest.Items.Add(Src.Items[i]); Src.Items.Delete(i); end; CountLabel.Caption := IntToStr( AvailableList.Items.Count) + ' available theatres.'; end; Figure 2: The AddLink OnClick event handler.

Figure 3: IntraWeb's debugging interface.

From the debugging interface, press [F9] (or select Run | Execute from the menu) to launch the browser automatically. Figure 4 shows what you will see in the browser, with the Add link added. I

couldn't believe it! I had just written a functional Web application in less than five minutes. Instant Web application; just add source code! I know it sounds too easy, but it really doesn't get any harder. Want to show a new form? Use the Show method. It doesn't get easier than that.

Figure 4: The application in Internet Explorer.

What you've seen so far is referred to as the form layout manager, and that's what IntraWeb uses by default, i.e. you design the form as you would a Delphi application, and the Web page will look the same. IntraWeb, however, has multiple layout managers, and you even can create your own. One of the alternate layout managers is a template processor that allows you to assign an HTML file to a form created using an HTML editor such as Microsoft FrontPage or Macromedia Dreamweaver. IntraWeb will merge the form and the HTML file during the rendering process. This allows your graphics people to design "the look" and allow you to handle the programming.

Complex Capabilities
Although the demo we just looked at is very simple, don't let this fool you into thinking IntraWeb can do only simple things. IntraWeb contains many demos, but my favorite is the dynamic chart shown in Figure 5. This chart is live in the browser. The user can play with the data without needing to request data from the server. A user can choose columns, rows, and even functions. The currently supported functions are Sum, Count, Minimum, Maximum, and Average. The dynamic chart is limited to bar charts and has other limitations. For more advanced charting needs, IntraWeb has support for TeeChart as well.

Figure 5: A dynamic chart.

IntraWeb supports two modes: application and page. We've been looking at application mode, which is best for creating Web applications. In application mode, IntraWeb handles all the details for you - session management, link management, everything. This mode is the easiest, by far, but it's at the expense of some flexibility. Page mode allows you to handle each page separately, and requires more work for the developer because you must handle state and links. However, page mode can be integrated with WebBroker or WebSnap to augment them. IntraWeb comes with two page-mode demos.

Deployment and Documentation

We're discussing Web applications, so deployment is an important consideration. In addition to the stand-alone debugger shown previously, IntraWeb applications can be deployed as self-contained Windows services, ISAPI DLLs, or Apache DSOs (Windows only). Deployment types can be altered easily by changing five lines of code (or less) and then recompiling. Aside from those few lines of code, the applications are identical. Documentation is the one weak part of IntraWeb. The documentation consists of 45 pages in Adobe Acrobat format, a help file, and documentation on the Web site. The Adobe Acrobat files consist of IntraWeb Manual (35 pages) and Intro to IntraWeb (10 pages). IntraWeb Manual contains some specifics, hints, techniques, and other documentation specific to IntraWeb. It contains a lot of useful information, but it needs to be expanded, specifically in the areas of form management, page mode, and custom component creation. AToZed Software promises that these topics and others are to come, and the company regularly releases documentation updates. IntraWeb also includes demos that demonstrate nearly every feature of IntraWeb, including database access, application mode, page mode, ISAPI DLL deployment, Apache DSO deployment, templates, WebBroker integration, and WebSnap integration. The help file documents many of the IntraWeb specifics, but many of the topics are blank. Most of the blank topics are those such as TIWListbox.ItemIndex, which are the same as their Delphi counterparts and thus not exactly vital to documentation. There's no substitute for documentation, but I rarely needed it anyway. Developing IntraWeb applications is so much like developing normal Delphi applications that things just come together naturally.

Technical Support

IntraWeb's technical support is probably better than any I have experienced from a vendor. I hope other vendors will take note. Technical support is provided by newsgroups. In the months that I have been part of AToZed Software's newsgroups, I cannot remember a single message that has gone unanswered. Most messages are answered within minutes, and it's rare for messages to go without a reply for more than a few hours, even on Sundays. Users also report bugs by using the newsgroups. Nearly all bugs are fixed within a few days, and certainly all critical ones are. The release versions tend to be quite stable, but there is parallel development on newer betas, which is where most of the bugs appear. IntraWeb 4 is the current release, but IntraWeb 5 is expected as a beta soon. IntraWeb already has a strong third-party program and support from several vendors. These include a Bold ( integration from Centillex Software, and TeeChart support from Steema Software ( TMS Software ( and Used-Disks Inc. also provide add-on component packs with additional IntraWeb components.

Pros and Cons

A fully functional evaluation edition of IntraWeb is available. The evaluation edition has no time limit and very modest restrictions; you can develop a fully functional application but you cannot deploy it. There's a lot to like about IntraWeb: true RAD Web development existing Delphi knowledge can be reused easily doesn't require Web-development experience extremely flexible and expandable framework open and flexible API third-party vendor support superb technical support The only major downside for IntraWeb is that its documentation could use some improvement.

IntraWeb is nothing short of phenomenal. I've been able to build robust Web applications that I couldn't have without IntraWeb. When I first started with IntraWeb, I barely knew HTML. IntraWeb also allows full control on several layers if you want to access HTML or JavaScript. Delphi makes Windows development incredibly easy with its VCL wrapper on top of the Windows API. IntraWeb does the same for Web development, with its architecture on top of HTML, JavaScript, and HTTP. I haven't been this excited about a product since Delphi debuted and freed developers from the bondage of the Windows API by delivering true RAD development without the limits of Visual Basic. Why Borland has not implemented WebSnap this way is a mystery to me. Paul Stockton has been a programmer with Barwick Systems Limited for 15 years. He develops database applications for many large organizations in the United Kingdom using both IBM AS/400s and PC systems. He is a jack-of-all-trades with PCs, whether he's building them, configuring networks, doing Web or graphic design, or dabbling with Delphi.

Informant Fact File

With IntraWeb, you can leverage your existing Delphi skills to develop fully functional Web applications and deploy them to a standard browser with no more effort than developing a normal Delphi application. In short, IntraWeb is Delphi.Web. If you're involved in Web development or plan to be, you need to try IntraWeb and see if it fits your needs. The product is compatible with Delphi 5 and Delphi 6, both Professional and Enterprise. Kylix and C++Builder versions are expected soon.

Using IntraWeb Page Mode with WebSnap - by John Kaster

Abstract: Chad Hower of AToZed Software shows how to use IntraWeb Page Mode with WebSnap

This article will provide a very brief introduction to IntraWeb and demonstrate how IntraWeb can be integrated with WebSnap. A demo will be built that uses WebSnap to provide the framework, login, and session management. IntraWeb will be used to provide the user interface. In this manner of integration, the products are quite complimentary.

What is IntraWeb?
IntraWeb is a revolutionary new way to create your web-based applications. IntraWeb allows you to create your applications in a true RAD manner by dragging and dropping components on a web form and defining events and setting properties the same way that you would in a normal Delphi application.

Development Modes
IntraWeb supports two modes of development, application mode and page mode. Application mode is for creating web applications. Application is easier to develop but a little less flexible. Application mode is developed just like a normal Delphi application with, ShowMessage, and much more. This article however will focus on page mode. For more information on application mode please see the Atozed Software website at Page mode is more flexible and essentially the same type of web development that you are accustomed to with Web Broker and WebSnap. Page mode is for developing websites, or applications that are made up of individual pages. Page mode is available by using page producers which can be used with Web Broker or WebSnap.

Description of Demo
The demo is a simple demo that takes a survey of two questions that are of vital importance to the programming community. The two questions are: 1. Which was the BEST Star Trek movie? 2. Which was the WORST Star Trek movie? It will then collect your vote and tabulate it with other voters. To see this, simply run the demo in the browser multiple times. After it tabulates the votes it will generate a small chart displaying the results. The demo source can be downloaded by downloading IntraWeb 4.0.27 or later at We have designed it to be simple as possible so as to make it easy to follow. It demonstrates the following:

1. 2. 3. 4. 5.

IntraWeb integration with WebSnap. Use of IntraWeb Page Mode. Use of WebSnap session management with IntraWeb. Use of WebSnap for control of authentication. Use of IntraWeb to provide the primary web interface

Creating the Demo

It is assumed that you are familiar with WebSnap and thus we will just show the IntraWeb specific parts in creating this demo. We started with a standard WebSnap application that contained login support using a TWebUserList and a TLoginFormAdapter. The first thing that must be done to use IntraWeb with WebSnap is to add a TIWModuleController. To simplify distribution and not require distribution of external files, IntraWeb serves internal files from its libraries. IntraWeb has several internal files and as a user you can add more using IntraWeb's API. TIWModuleController hooks into WebSnap's dispatch mechanism and provides this functionality and other core IntraWeb requirements. This component can also be used to use IntraWeb with WebBroker and is demonstrated in the GuessWB demo that is provided with IntraWeb. For the TIWModuleController to be effective, the application module also needs a TWebDispatcher. Open the application module and add a TWebDispatcher (from the Internet tab) and then a TIWModuleController (from the IntraWeb Control tab). No further changes are required, IntraWeb and WebSnap will do the rest. Your application module should now look like this:

Next we created a new WebSnap page module. To do this we selected File : New : Other : WebSnap tab : WebSnap Page Module. The dialog is shown here:

After OK is clicked, Delphi will display the New WebSnap Page Module dialog as shown here:

Make the settings match the settings as shown in the figure above and select OK. Delphi will now create a new WebSnap Page Module. It should look like this:

Delete the TPageProducer and create a TIWPageProducer (from the IntraWeb Control tab). The page module should now look like this:

Save the page module and name it Page1Module.pas. Now we need to create an IntraWeb page form. Select File : New : Other : IntraWeb : Page Form as shown below and select OK.

Delphi will then create an IntraWeb Page Form as shown here:

Save the form as Page1Form.pas. Now lets go back and link Page1Module to Page1Form. To do this create an OnGetForm event for the TIWPageProducer. The event needs to look like this:

procedure TPage1.IWPageProducer1GetForm(ASender: TIWPageProducer; AWebApplication: TIWApplication; var VForm: TIWPageForm); begin VForm := TformPage1.Create(AWebApplication); end;

This creates an instance of TformPage1 on demand. So that the unit will compile IWApplication and IWPageForm must also be added to the uses clause. Now let's go back to Page1Form and create our survey questions. We've created two TIWLabel components, two TIWComboboxes, one TIWButton, and one TIWText. For the comboboxes we have also set the RequireInput = False. Our Page1Form now looks like this:

Next we will add the code for the form's OnCreate event. Double click on the form and enter this code. The code merely loads the text and identifying numbers into the combo boxes.

procedure TPage1.IWPageProducer1GetForm(ASender: TIWPageProducer; AWebApplication: TIWApplication; var VForm: TIWPageForm); begin VForm := TformPage1.Create(AWebApplication); end;

Now we will add an OnClick event for the button. Double click on the button and add this code:

procedure TformPage1.butnVoteClick(Sender: Tobject); var LBest: TSTMovie; LWorst: TSTMovie; begin LBest := miMotionPicture; LWorst := miMotionPicture; if cmboBest.ItemIndex = -1 then begin textMsg.Lines.Text := 'Please select a choice for best Star Trek movie.'; end else if cmboWorst.ItemIndex = -1 then begin textMsg.Lines.Text := 'Please select a choice for worst Star Trek movie.'; end else begin LBest := TSTMovie(cmboBest.Items.Objects[cmboBest.ItemIndex]); LWorst := TSTMovie(cmboWorst.Items.Objects[cmboWorst.ItemIndex]); if LBest = LWorst then begin textMsg.Lines.Text := 'Sorry - but you cannot pick the same movie for best and worst.'; end else begin

if WebContext.Session.Values['Confirm'] <> 'Y' then begin if LBest = miFinalFrontier then begin textMsg.Lines.Text := 'Ugh. The Final Frontier was truly horrid. Are you sure that is' + ' your choice for best?'; butnVote.Caption := 'Vote with my questionable choice anyways'; WebContext.Session.Values['Confirm'] := 'Y'; end else if LBest = miVoyageHome then begin textMsg.Lines.Text := 'Good choice! The Voyage home was good wasn''t it?'; butnVote.Caption := 'Record my vote!'; WebContext.Session.Values['Confirm'] := 'Y'; end; end; end; end; textMsg.Visible := textMsg.Lines.Count > 0; if not textMsg.Visible then begin RecordVote(LBest, Lworst); ProduceResponse := False; DispatchPageName('PageResults', WebContext.Response, []); end; end;

Now we could spend a lot of time explaining the above code. But did you notice something? Its all standard Delphi code! So we'll just explain a few lines of interest. The code checks to see if the user has selected information, and also makes sure that they do not select the same movie for both choices. It also enters in its personal opinion about certain choices and displays messages to the user by making the TIWText component visible. If the TIWText component is not made visible, not messages are displayed and all is well. In this case the code calls RecordVote which is a procedure in Global.pas which is part of the demo. It then sets ProduceResponse to False. This tells IntraWeb not to render this page because we will render it manually, or give WebSnap instructions to do so. Finally we give WebSnap instructions to render a different page module to display the results. There are a few properties on the form itself that we must set as well.

1. Set PostToSelf to true. This instructs the form to generate links that will send the data
back to this same form. FormAction can be set if you wish the data to be submitted to another form. FormAction and PostToSelf (When true) are mutually exclusive. 2. Set AutoProcess to true. This instructs the form to automatically parse the HTTP variables and set the component states accordingly. If you wish to control this process manually, you would leave AutoProcess to false. Next we will create another Page Module and Page Form. The steps are pretty much like the previous one so we will not waste space on this. Instead we will start with a bank page form, PageResultsForm.pas. We have added one TIWImage and loaded a bitmap into it. It looks like this:

For this form we have created only one event. We have put some drawing code in the OnRender event. The OnRender event occurs each time IntraWeb renders a form, prior to it actually being rendered. Here is the code for the OnRender:

procedure TformResults.IWPageFormRender(Sender: Tobject); var i: TSTMovie; LMaxBest: Integer; LMaxWorst: Integer; LMaxWidth: Integer; LVotesBest: Tlist; LVotesWorst: Tlist; begin LMaxBest := 0; LMaxWorst := 0; LMaxWidth := 0;

LVotesBest := TList.Create; try LVotesWorst := TList.Create; try GetVotes(LVotesBest, LvotesWorst); with imagResults.Picture.Bitmap.Canvas do begin Brush.Style := bsClear; Font.Color := clBlue; Font.Name := 'Script'; Font.Size := 18; for i := Low(i) to High(i) do begin TextOut(85, 98 + 24 * Ord(i), Gmovies[i]); LMaxWidth := Max(LMaxWidth, TextWidth(GMovies[i])); LMaxBest := Max(LMaxBest, Integer(LVotesBest[Ord(i)])); LMaxWorst := Max(LMaxWorst, Integer(LVotesWorst[Ord(i)])); end; TextOut(330, 74, 'Best'); TextOut(480, 74, 'Worst'); // Brush.Style := bsSolid; for i := Low(i) to High(i) do begin Brush.Color := Gcolors[i]; FillRect(Rect(310, 98 + 24 * Ord(i) , 310 + Trunc((Integer(LVotesBest[Ord(i)]) / LMaxBest) * 150) , 98 + 24 * Ord(i) + 20)); Brush.Color := GColors[TSTMovie(Ord(High(i)) Ord(i))]; FillRect(Rect(480, 98 + 24 * Ord(i) , 480 + Trunc((Integer(LVotesWorst[Ord(i)]) / LMaxWorst) * 150) , 98 + 24 * Ord(i) + 20)); end; end; finally FreeAndNil(LVotesWorst); end; finally FreeAndNil(LVotesBest); end; end;

Notice something? It's all pure Delphi code again. The code merely takes the tabulated results and creates a simplistic chart.

Running the Demo

We have now covered the important parts of the demo itself. Let's see what it looks like when we run it. First compile and run the demo and then run the Web Application Debugger from the Tools menu. From the Web Application Debugger click on the URL link and then select WebSnapSurvey.Survey in the browser. This will start our demo application. It should look like this:

This screen is produced by WebSnaps login adapter. Enter test for the user name and test for the password and click Login. This screen will now appear:

This is the form that we created in Page1Form.pas. Notice it looks just like the form? We did not even have to write any HTML! We just created the form like any other Delphi form. If you want, you can use WebBroker style templates to modify the look using an HTML page. Some of the other IntraWeb demos demonstrate this. Before selecting choices, click Vote. You will notice that the page is returned and appears like this:

Notice the error message? That was done in Delphi code merely by setting the lines property of the TWIText component and setting its visible property to true. Ok let's move on. Now select your choices and click vote. Now it will display the result screen:

This was generated by our code in the OnRender event in PageResultsForm. The results page is cumulative, so if we vote several times by using the URL again in the Web Application Debugger this page will tabulate all the votes. After serveral votes it might look something like this:

This article demonstrates just some of the very basic features of IntraWeb while also showing how to integrate with WebSnap. IntraWeb can be use to expand WebSnap into Uncharted territory and beyond.

Using XMLBroker with IntraWeb - by Guinther Pauli

Abstract: This article will explain how to use the XMLBroker in a IntraWeb application, caching data and updates in browser. And finally, how to solve this updates to database server.

Delphi 5 brought the Internet Express technology that allows the creation of Thin-Clients to MultiTier applications, based on a Web Browser. By using the XMLBroker we can connect it to a DataSetProvider and extract information from an application server in a XML format, which is sent to the browser. The data is then updated (creating a local cache called "delta") and sent back to the XMLBroker, which repasses the updating to the o DataSetProvider and finally to database server. The pages interface (the HTML code) is produced by the InetXPageProducer (former MidasPageProducer). The javaScript codes carry out the workability of the page, such as the manipulation of the XML data packet (this is basically done by xmldb.js and xmldisp.js files). The most interesting aspect of this architecture is that the user can work locally in the records, doing updates, inserts and deletes, without the need of a new requisition to the server in each operation. All the updates are sent to the server only when the user asks for the Apply command. The IntraWeb offers a similar option, available through the components of the IW Client Side palette. The problem is that the data sent to the browser are currently read-only. In this article we will create an IntraWeb application combining XMLBroker features. What we will basically do is to adapt the code generated by the InetXPageProducer to the IntraWeb. To build this example you need IntraWeb 5.1 or higher and Delphi Enterprise. Some features used here are not available in the IntraWeb 5.0 and Delphi Professional. The Upgrade to IntraWeb 5.1 is free for Delphi 7 users.

The XMLBroker architecture with IntraWeb

The following picture shows the XMLBroker architecture, using IntraWeb as Web server application.

Creating the application and the database connection

Start a new IntraWeb Stand Alone application with a DataModule (File|New|Other|IntraWeb). Put a SQLConnection (from dbExpress) component in the DataModule and configure a connection to the Interbase EMPLOYEE.GDB database. After that, set its LoginPrompt property to False. Put a SQLDataSet (from dbExpress) and set its SQLConnection property. Type select CUST_NO, CUSTOMER, CONTACT_FIRST, CONTACT_LAST from CUSTOMER in its CommandText property.

Put a DataSetProvider (from Data Access) component in the DataModule and set its DataSet property to SQLDataSet1. Put also a XMLBroker (from InternetExpress) and set its ProviderName property to DataSetProvider1, and Connected to True.

In this example we will not create an application server. So the DataSetProvider and XMLBroker will remain in the same DataModule. If you want to use a application server the steps are basically the same.

Creating the main form

Go to the main form and using IWLabels, IWEdits and IWButtons (from IW Standard) build your user interface, some like the picture below. Here we will use only the main table fields. Define the Name property of the IWEdits components to CUSTNO, CUSTOMER, CONTACTFIRST and CONTACTLAST respectively.

Here is the code that you must put in the ScriptEvents property (OnClick) of each one of the buttons: Button First (|<) Prior (<) Next (>) Last (>|) Insert ScriptEvents (OnClick) If(xml_ready)FieldGroup1_Disp.first(); If(xml_ready)FieldGroup1_Disp.up(); If(xml_ready)FieldGroup1_Disp.down(); If(xml_ready)FieldGroup1_Disp.last(); If(xml_ready)FieldGroup1_Disp.newRow();

Delete Undo Post Apply

if(xml_ready)FieldGroup1_Disp.removeRow(); if(xml_ready)FieldGroup1_Disp.undo(); if(xml_ready); document.SubmitForm.elements.IW_Action.value='IWBUTTON9'; if(xml_ready)XMLBroker1_RS.Apply(Submit_XMLBroker1, Submit_XMLBroker1.postdelta);

IWBUTTON9 in this case is the name of Apply Button Remember that JavaScript is case-sensitive!

Setting the WebMidas JavaScript files

Create a directory called files in the directory where you saved the project files (or where the stand alone application will be run). Copy to this directory the xmldb.js and xmldisp.js files that are in the directory $(DELPHI)/Source/WebMidas. We need to do a little modification in the xmldb.js file so that there is not a conflict with the functions defined by the IntraWeb. Open this file and on line 313 change the declaration "Validate" for "DoValidate". Do the same on line 409. Attention: Note that even using IntraWeb you are making use of MIDAS/DataSnap technologies. The use of WebMidas technology requires a license from Delphi Enterprise. See the Borland documentation for further information about the developing with MIDAS/DataSnap. The next step is to create a JavaScript file which defines the global variables used by WebMidas. Create a file called defvars.js in the same directory (files). The content of the file is the following:
var var var var var var XMLBroker1_RS; DataForm1; FieldGroup1_Names; FieldGroup1_IDs; FieldGroup1_Disp; Submit_XMLBroker1;

Note that here the global variables are just defined. We initialize the variables in a second file that you must create in the same directory files, with the name initvars.js. Here is the content of the file:
XMLBroker1_RS = new xmlRowSet(XMLPACKET, null, null); DataForm1 = document.forms['SubmitForm']; FieldGroup1_Names = new Array("CUST_NO", "CUSTOMER", "CONTACT_FIRST","CONTACT_LAST");

FieldGroup1_IDs = new Array(DataForm1.CUSTNO, DataForm1.CUSTOMER, DataForm1.CONTACTFIRST, DataForm1.CONTACTLAST); FieldGroup1_Disp = new xmlDisplay(XMLBroker1_RS, FieldGroup1_IDs, FieldGroup1_Names, null); Submit_XMLBroker1 = document.forms['SubmitForm']; xml_ready=true;

Adding the JavaScript files

The next step is to include the WebMidas script files to document and the file that defines the global variables. We can do this using AddScriptFile method of TIWAppForm. In the OnCreate event of main form type this:
procedure TIWForm1.IWAppFormCreate(Sender: TObject); begin AddScriptFile('/files/xmldb.js'); AddScriptFile('/files/xmldisp.js'); AddScriptFile('/files/defvars.js'); end;

Note that we do not include the initialization file of the JavaScript (initvars.js) variables. This code must be added to the initialization of the HTML document, as we will do further on using AddToInitProc.

Initializing the XML packet the and WebMidas variables

Now we will add the the XML data packet to the document and include in the Initialize function the JavaScript code that initializes the WebMidas variables. In the OnRender event of the main form write the following:
procedure TIWForm1.IWAppFormRender(Sender: TObject); var SL : TStringList; V : OleVariant; I : integer; XML : TIWHTMLTag; //declare IWHTMLTag in uses begin XML:=TIWHTMLTag.CreateTag('XML'); try XML.AddStringParam('ID','XMLPACKET'); XML.Contents.AddText(DataModule1.XMLBroker1.GetXMLRecords(I ,V,[])); ExtraHeader.Clear; // clear ExtraHeaders ExtraHeader.Add(XML.Render); // add the XML Data Packet finally XML.Free; end; // add initialization variables to the Initialize function

of IW document SL:=TStringList.create; try SL.LoadFromFile('files/initvars.js'); AddToInitProc(SL.Text); finally SL.Free; end; end;

Remember to declare IWHTMLTag in uses.

Getting the Delta and sending it to the AppServer

Open the HiddenFields property of the IntraWeb main form and add the following line: postdelta= This is the field that will keep the Delta which will be sent back to the Web server application. The next step is to get the delta in the server and repass it to the XMLBroker. When we work with InternetExpress applications, the XMLBroker is automatically registered as the main component of dispatch. XMLBroker get the Delta and repassing it to the server application (DataSetProvider), without the need of requisition handle. We can also create a event handler for its OnGetResponse and apply the cache manually using the method ApplyXMLUpdates. Using XMLBroker with IntraWeb we can't to use this auto dispacth mechanism To manually get and apply the delta in the IntraWeb Application, in the OnClick event of IWButton9 type the following:
delta:=DataModule1.XMLBroker1.GetDelta(WebApplication.Request) ; // get delta DataModule1.XMLBroker1.ApplyXMLUpdates(delta,I); // apply delta

Declare a local string variable named delta, and an Integer named I. In the start of this article we place a Javascript code in the OnClick event of this button, to send the delta to the IntraWeb server. This function submit the form internally, without the IntraWeb handling. As we manually submit the form, then we have a problem, the OnClick event in the IntraWeb server never fire. To do this, we need to set manually a HiddenField named IW_Action (already defined by IW) to point to IWBUTTON9. We made this in the beginning of the article, in OnClick ScriptEvent of IWButton9, see:


Note that, in a normal IntraWeb application, this is made internally in the SubmitClick function. Then, when the form is submited, IntraWeb read this hidden field to map the right event in the server, in this case, OnClick of IWButton9.

Testing the application

Run the application. Include, update and delete some records, and note that there is no communication with the Web server. Click then on the button Apply to send the delta (XML) to the server that will repass the updated data to the XMLBroker. The following pictures shows an update in the two first records, and after the Apply we can see that the o Delta was applied correctly in the Interbase database.

Using visual form inheritance with IntraWeb 5.1 in Delphi 7

Abstract: This article explains a way to be able to use visual form inheritance with IntraWeb (5.1). Something that normally is not working.

When I started with my first real application in IntraWeb, I wanted to make a consistent layout through out my application. Since with IntraWeb you can make a web application just like a normal Delphi application: my first thought was: (visual) form inheritance (VFI). So I started happily programming making a baseform as a parent for all my other forms, putting on it a title bar, and started inheriting from it. And it worked: I had the title bar on all my forms! But after I started programming really functional forms, I soon also wanted to change something about my baseform, make the layout a bit nicer and better fitting with the forms I was making. And then it happened: I had added something to my baseform, compiled the application and it just gave an exception: "Control 'IWButton1' has no parent window". I hadn't changed anything really, except enhancing my baseform: and there wasn't even a IWButton1 on my baseform, it was on my mainform! Well after a little debugging, I looked at the IntraWeb newsgroups and it's website and soon found the answer: IntraWeb doesn't support visual form inheritance. You can use inherited code, but you can't inherit the visual layout...

Finding the problem...

Since I am a stubborn person (I wanted to use visual form inheritance!), and in my opinion problems are there to be solved, I started digging deeper in the problem. With the help of Delphi's VCL code (one of the things I love most about Delphi: you can always look at the source!) I soon found out in which part I had to search for the problem: the SetZOrderPosition method of TControl. When you add controls to a form you have inherited from (the baseform)

the ordering of the controls on your descendant forms (in my case the Mainform) changes. You can see this ordering when you look at the dfm file of a descendant form: you see numbers in brackets [] after the controls. These numbers tell Delphi in which order the controls appear. In this SetZOrderPosition method there is a call to ValidParentForm (found in Forms.pas) that returns the parent form of the current control if that parent forms is a descendant of TCustomForm. And that was the problem: a TIWAppForm is not a descendant of TCustomForm!

...and trying to fix it.

Well only finding the problem doesn't solve it, I needed to find a way to fix it. My first thought was: I wanted that Borland had made ValidParentForm a virtual protected method of TControl, so anyone could override it, and the guys from IntraWeb could have made a special version that worked with IntraWeb forms. But since that wasn't the case, I had to go one level up to the SetZOrderPosition method. And found out that that one is private to TControl, so no chance of overriding that. (B.T.W. If that one could have be overridden it would have also meant that it had to be done in TIWBaseControl: and I would not be able to do that.) So I needed to go up one level: the caller of SetZOrderPosition which was in this case the SetChildOrder method of TWinControl, where this TWinControl was actually my Mainform. And the nice news was that SetChildOrder of TWinControl could be overridden! However if I did that there could be other problems because SetZOrderPosition was also called by other methods in TControl and TWinControl. But if that happened I would find out sooner or later. Seeing that I needed to override SetChildOrder of my Mainform, and since that one inherited from my baseform: I put my implementation of SetChildOrder in my baseform. My implementation looked as follows:

So if the Child is a TIWBaseControl I call a special implementation of SetZOrderPosition else I just call the inherited version. That special implementation of SetZOrderPosition I put in a class called TIWBaseControlHelper:

To hack or not to hack?

Until so far it was simple. But now the real challenges appeared: I had to copy the implementation of SetZOrderPosition, but that implementation used a private field called FControls (see the VCL implementation of TControl.SetZOrderPosition in the Controls.pas unit). So I looked at what does the SetZOrderPosition has to do: it has to put itself at a certain position in it's parent list of controls. How can it do that, well look at the code I produced:

This code was of course inspired by the original TControl implementation: but the important part I had to rewrite. What it does is it first checks if it has a parent, then it searches for it's current position in the parent's control list and sees if it's new position is not the same. When it finds out it has to reposition, the hacking begins. We can't manipulate the parent's control list directly, but we can indirectly through the parent property of all the controls in the control list. So what I do is make a copy of the current control list and reposition our self in there. Then I

set the parent of all the controls currently in the list to nil, so they are removed from the list and after that I add them again (in the correct order) to the list by setting their parent property back. So this results in a correctly ordered list. But this is not all that has to be done in this method! If it was we wouldn't have had any visual form inheritance problems, because this part already worked in the TControl implementation. The problem lied in the call to ValidParentForm in that implementation. First I thought I could just remove that call from my implementation, but I wasn't really sure and since the solution was not so hard, I made a call to a new function ValidParentIWForm. This function was simply based on the equivalent functions in Forms, I copied them and replaced references to TCustomForm to TIWBaseForm:

(I might be violating a little copyright of Borland here, but since this is actually the most obvious implementation and you can't use it if you don't have Delphi: I hope Borland allows me to publish it.) Now only one thing in my SetZOrderPosition code might need some explanation. I needed to call the PalletteChanged method of the ParentForm, but that is a protected method of TControl, so I used a standard hack to call a protected method: define a descendant class, and call the method by type casting to that descendant class:

Trying it out
And now the excitement begins: does it all work? So I started running my web application: and it gave no error! To really test it I made a lot of changes to my baseform, I made changes to my mainform and other forms: and it kept on working. I also changed the order of the controls on my baseform and mainform by selecting the control and right-click, choose Control -> sent to back and bring to front, since that actually manipulates that Z-Ordering, but it kept working.

So this finishes my solution for using visual form inheritance (VFI) with IntraWeb 5.1(.28) in Delphi 7 in application mode. We are using it for quite some time now, and haven't run into any bugs. You can get the source of this solution, including a small test project at codecentral. Included in that source is a TIWBaseVFIForm (in IWBaseVFIForm.pas) that you can use to inherited from. Of course you can also just copy the code from that form to your own base form. Remember one thing when using this solution: the developer of IntraWeb doesn't support VFI, so I have no idea if it will work for other versions of IntraWeb nor if it will work with pagemode! I also haven't tested this code with IntraWeb in Delphi 5 or 6, but a quick scan of the relevant source code of those implementations of TControl doesn't show any possible problems: so just try it out.