IntraWeb Tutorial
IntraWeb Tutorial
IntraWeb Tutorial
Introduction
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.
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:
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:
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:
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.
Welcome!
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
Prerequisites
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 - http://www.atozedsoftware.com) 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)
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:
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:
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.
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:
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:
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:
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:
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:
Conclusion
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.
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 (http://atozedsoftware.com) to deploy application mode IntraWeb applications.
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.
IntraWeb
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.
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.
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.
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.
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.
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 (http://www.boldsoft.com) integration from Centillex Software, and TeeChart support from Steema Software (http://www.teechart.com). TMS Software (http://www.tmssoftware.com) and Used-Disks Inc. also provide add-on component packs with additional IntraWeb components.
Conclusion
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.
Summary
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 form.show, 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 http://www.atozedsoftware.com/ 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 http://www.atozedsoftware.com. 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
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.
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.
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:
Conclusion
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.
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.
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.
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();
IWBUTTON9 in this case is the name of Apply Button Remember that JavaScript is case-sensitive!
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;
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.
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:
document.SubmitForm.elements.IW_Action.value='IWBUTTON9';
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.
Introduction
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...
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!
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:
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.
Conclusion
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.