分享

使用intraweb进行web编程

 frie 2005-08-08

Delphi2以后,Chad Z. Hower就一直在为建立一种简化Web程序开发的Delphi架构而努力,这种简化的核心思想就是使开发Web程序像开发普通窗口程序一样简单并且可视化。一些程序员了解动态HTMLJavaScript Cascading Style Sheets和最新的互联网技术;而另一些程序员则想像创建VCLCLX应用程序那样创建Web程序。

IntraWeb就是应第二种开发者的需求而问世的,她功能强大,即便是专业的Web程序员也能够从中受益。用Chad的话来说,IntraWeb是用来开发Web程序而不是用来创建网站的。此外,IntraWeb组件可用于特有的应用程序或者是WebBroker WebSnap应用程序。

在本章我不能详述IntraWeb的每一个细节,安装后,在Delphi上分布于数个组件板共计50个组件之多,实在太大了。我计划讲解一下基础内容,您可以有选择地用于您手头的项目或是那些项目中的部分内容。

提示:在Delphi7光盘中有IntraWebPDF版手册。如果您找不到,可以到Atozed Software公司的网站上去下载。关于IntraWeb的技术支持,可以参考Borland的新闻组。

IntraWeb简介

IntraWebAtozed Software公司出品的组件库。在Delphi7的专业版和企业版中有相应版本的IntraWeb。专业版的IntraWeb只能用于页模式(Page mode),关于页模式本章稍后将会提到。尽管Delphi7Borland公司的第一版包含该组件集的集成开发环境,但IntraWeb已经发展有几年了,受到了相当好的评价和支持,包括很多第三方组件开发商。

提示:

尽管您不能得到核心源代码(需购买),IntraWeb体系架构是完全开放的。并且所有组件的源代码随意可得。虽然IntraWebDelphi标准安装的一部分,但同样适用于Kylix。只要小心编写,IntraWeb程序完全可以实现跨平台。

注:除了Delphi Kylix版外,IntraWeb还有C++ BuilderJava版。.Net版正在开发中,将会随Delphi for .NetDelphi 8)一起发布。

如果您拥有正版Delphi7,你完全能够收到一个重大的升级信息,并且可以升级到IntraWeb5.1企业版,包括升级文档和技术支持。(目前版本为7.19——译者)

从网站到Web程序

正如前面所讲,IntraWeb背后的思想是构建Web程序而不是网站。当您使用WebBrokerWebSnap时,你以Web pagesPage Producers术语在思考,同时您的工作紧紧地和HTML层次的网页制作联系在一起。而用IntraWeb时,您想的是组件、属性和事件,就像是在Delphi中作可视开发一样。

比如,创建一个新的IntraWeb应用程序,选择File ? New ? Other,在新项目对话框中移到IntraWeb页,然后选择Stand Alone Application。在接下来的对话框中(此对话框是Delphi的而不是IntraWeb的向导)你可以选择一个已经存在的文件夹或是输入一个新文件夹(系统会自动创建,之所以在此提及,是因为该对话框不是很清楚)。最终的程序包含一个项目文件和两个不同的单元(稍后我会讲到它的结构)。

现在,让我们创建一个例程(随书源代码中叫做IWSimpleApp),步骤如下:

1、  移到程序的主窗体,从组件板中的IW Standard页中选择一个按钮,一个文本编辑框和一个列表框添加到窗体。注意不是组件板中Standard页中的VCL组件,而是相应的IntraWeb组件:IWButtonIWEditIWListbox

2、  像下面那样调整它们的属性:

object IWButton1: TIWButton
  Caption = ‘Add Item‘
end
object IWEdit1: TIWEdit
  Text = ‘four‘
end
object IWListbox1: TIWListbox
  Items.Strings = (
    ‘one‘
    ‘two‘
    ‘three‘)
end

 

3、  双击按钮组件编写OnClick事件,代码如下:

procedure TformMain.IWButton1Click(Sender: TObject);
begin
  IWListBox1.Items.Add (IWEdit1.Text);
end;

 

如图21.1所示的web程序(图中所示的是多两个按钮的最终版本)能够把文本添加到列表框,创建它仅需这几步。当你运行该程序时需要注意的是你每次单击按钮,浏览器都会向程序发送一个新的请求,该请求将会驱动Delphi事件句柄产生一个新的基于窗体上组件新状态的HTML页。

当您执行该程序时,您看不到程序输出的浏览器,而是一个IntraWeb控制器窗口(见图21.2)。一个stand-alone IntraWeb应用程序是一个HTTP服务器,这一点在下一部分里会有详细的阐述。您所看到的这个窗口是由每个stand-alone IntraWeb应用程序的项目文件中默认创建的IWRun函数来调用管理的。您可以在该调试窗口中选择一个浏览器,并通过它来运行程序,或者把URL拷贝到剪切板,然后粘贴到您的浏览器中。程序默认使用一个随机端口,该端口每次执行都不相同,因此,每次执行时的URL都不同。您可以通过选择服务器设计器(有点像数据模块)设定port端口属性来改变这种行为。在该例中我用的是8080(一个普通的HTTP端口),当然,其他值也可以。

IntraWeb程序的代码主要在服务器端,但IntraWeb也能够产生JavaScript来控制程序的一些特性,因此在客户端也可以执行特别的代码。您可以通过使用特别的客户端组件或者写一些特别的JavaScript代码来实现。作为一个比较,下面例程IWSimpleApp中的两个按钮通过不同的方法实现显示一个消息框。

两个按钮中的IWButton2使用Delphi代码利用服务器端事件来显示一个消息框。

procedure TformMain.IWButton2Click(Sender: TObject);
var
  nItem: Integer;
begin
  nItem := IWListbox1.ItemIndex;
  if nItem >= 0 then
    WebApplication.ShowMessage (IWListBox1.Items [nItem])
  else
    WebApplication.ShowMessage (‘No item selected‘);
end;

 

 

这两个按钮中的第二个(IWButton3)使用了JavaScript,这是通过在按钮的ScriptEvents属性的属性编辑器中正确地设置JavaScript事件句柄来实现在Delphi程序中嵌入JavaScript的。

IntraWeb事件脚本编辑器

初探幕后

看到了吧,创建一个IntraWeb应用程序就和创建一个基于窗体的Delphi应用程序一样简单:在窗体上放置组件然后处理它们的事件。当然,效果是不同的,毕竟这样的程序是运行在浏览器中。为了让您明白到底是怎样工作的,我们简要地看一下这个简单的程序背后。这样做会帮助您理解设置组件属性和使用组件编程的效果。

这是一个基于浏览器的程序,因此没有什么比看一下程序送到浏览器的HTML代码能更好地理解它工作机制的方式了。打开IWSimpleApp程序源代码页,会发现分成了三部分。第一部分是类似下面的样式列表:

.IWEDIT1CSS {position:absolute;left:40;top:40;z-index:100;
  font-style:normal;font-size:10pt;text-decoration:none;}

IntraWeb使用样式不仅能确定每个组件的外观,如字体和颜色,而且能够确定组件的位置,默认方式是相对位置定位。每个样式受组件的很多属性影响,如果您有样式表的知识,您可以简单地试验一下;如果不熟悉样式表,那就相信IntraWeb吧,它会把组件在web页上绘制得很好。

The second block consists of JavaScript scripting. The main script block contains initialization code and the code of client-side event handlers for the components, like the following:

第二块包含了JavaScript的描述。主要的脚本块包含初使化代码和组件的客户端事件处理代码,例如:

function IWBUTTON1_OnClick(ASender) {
  return SubmitClickConfirm(‘IWBUTTON1‘,‘‘, true, ‘‘);
}

The scripting section of the page has also references to other files required by the browser and made available by IntraWeb. Some of these files are generic; others are tied to the specific browser: IntraWeb detects the browser being used and returns different JavaScript code and base JavaScript files.

脚本还涉及一些浏览器需要的由IntraWeb产生的其他文件。这些文件有些是通用的,而有些是捆绑给特定的浏览器的:IntraWeb能够探测出所用浏览器,从而返回不同的JavaScript代码和基本JavaScript文件。

注意:因为不是所有浏览器都能识别JavaScript的,所以IntraWeb只支持部分浏览器。支持的浏览器有最新版的Microsoft Internet Explorer、Netscape Navigator和开放源代码的 Mozilla (我用的就是)。由于Opera支持JavaScript更有限,所以默认情况下如被识别,IntraWeb就会发出一个错误信息(依赖于controller的SupportBrowsers属性)。Opera能够和免费的Arcana组件一起使用,在IW 5.1版中被正式支持。记住浏览器可能会伪造身份:比如,Opera常常被认成IE。为使站点不受浏览器的限制,设置支持更多的浏览器,却又可能会导致运行错误和矛盾。

第三部分HTML是定义页面结构的。在Body标记内部是一个带有将要执行的动作的form标记(同一行):

<form onsubmit="return FormDefaultSubmit();" name="SubmitForm"
  action="/EXEC/3/DC323E01B09C83224E57E240" method="POST">

form标记依附于指定的用户界面组件,如按钮和编辑框:

<input type="TEXT" name="IWEDIT1" size="17" value="four"
  id="IWEDIT1" class="IWEDIT1CSS">
<input value="Add Item" name="IWBUTTON1" type="button"
  onclick="return IWBUTTON1_OnClick(this);"
  id="IWBUTTON1" class="IWBUTTON1CSS">

窗体还隐藏了一些用于前后传递信息的IntraWeb组件。不过,URL在IntraWeb中是最重要的传递信息方式。在程序中URL类似下面:

http://127.0.0.1:8080/EXEC/2/DC323E01B09C83224E57E240

第一部分是IP地址和stand-alone  IntraWeb应用程序端口(使用不同的体系结构将会不一样), EXEC 命令后面是累计请求次数,后面是session ID。稍后我们会讨论Session。但现在我们就可以说IntraWeb使用URL记号代替cookies从而忽略浏览器的设置而使应用程序可用。如果你愿意,可以通过设置controller的TrackMode属性,来使用cookies代替URL标记。

IntraWeb 体系结构

在演示如何使用Delphi7中其他IntraWeb组件之前,让我们来讨论一下IntraWeb的关键东西: Web开发的不同开发模式,即AppMode和PageMode。前者可以开发成一个独立运行的可执行程序,也可以开发成ISAPI DLL,甚至Apache Modules。AppMode能够真正展示IntraWeb的优秀特征。而PageMode则是WebBroker或WebSnap程序的IntraWeb简版插件,可以开发除可执行程序之外的任何程序,如ISAPI、Apache Module、CGI等。IntraWeb基于这两种模式提供了三种不同但又有所交叉的体系结构:

Standalone Mode 提供了一个像第一个例程那样的自己的Web Server。这一点对于调试来说相当便利(你可以在开发环境中直接运行并且可以随处设置断点)。Standalone mode开发的程序可以运行在内联网(Intranets)并且让用户在自己的电脑上脱机使用Web 界面工作。如果带参数 -install 运行stand-alone程序,程序将会以服务形式工作,不显示对话框界面。Standalone mode提供开发使用IntraWeb自身作为Web服务器的AppMode程序的一种方法。

Application Mode  能够开发商务web服务,建立Apache module或是IIS动态链接库。Application mode具备包括会话期管理在内的IntraWeb全部特性,并且是开发通过Web即可升级的网络程序首选。准确地说,Application mode可以开发成为stand-alone程序,ISAPI动态链接库,或是Apache modules。

Page Mode  提供一个整合IntraWeb页面和WebBroker与WebSnap应用程序的方法。Page mode能够向现有的程序或是基于其他技术的动态交互站点注入IntraWeb特性,提供更好的交互手段。Page mode是在CGI程序中使用IntraWeb技术的唯一选择,不过,Page mode不具有会话期管理特性,而具备该特性的Stand-alone IntraWeb程序却不支持Page mode。

本章后面的例子,为了追求简单和调试方便主要使用Stand alone模式。但同时也会涉及Page mode。

 

Delphi从入门到精通》第21  第二部分

创建IntraWeb应用程序

创建IntraWeb应用程序,有很多组件可用。不妨看一下Delphi组件板中的IW Standard页,会给您留下深刻的印象,从简单的按钮、复选框、单选框、编辑框、列表框到迷人的树形控件、菜单、计时器、表格和链接应有尽有。我不想举例描述每个组件的用法,只想通过几个例子,阐述IntraWeb的体系结构,当然顺便也会介绍用到的组件。

我创建了一个例程(叫IWTree),演示了IntraWeb的菜单和树形控件的用法,同时也说明了如何动态创建组件。IntraWeb菜单通过引入常规Delphi菜单内容来工作的,这很容易,只需简单地把AttachedMenu设置成Tmenu组件即可:

object MainMenu1: TMainMenu
  object Tree1: TMenuItem
    object ExpandAll1: TMenuItem
    object CollapseAll1: TMenuItem
    object N1: TMenuItem
    object EnlargeFont1: TMenuItem
    object ReduceFont1: TMenuItem
  end
  object About1: TMenuItem
    object Application1: TMenuItem
    object TreeContents1: TMenuItem
  end
end
object IWMenu1: TIWMenu
  AttachedMenu = MainMenu1
  Orientation = iwOHorizontal
end

菜单项运行时处理OnClick事件,是以链接形式实现的。看一下图21.3,这是展示菜单的例程的运行效果。例程中的另外一个组件是树形控件,在例子中预置了很多节点。该组件通过很多JavaScript代码来实现在浏览器中(不需要调用服务器代码)直接控制树形控件节点的展开和收叠。同时,菜单中还有控制树形控件节点展开和收叠以及控制字体大小的菜单项。下面列出其中两个事件代码:

procedure TformTree.ExpandAll1Click(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to IWTreeView1.Items.Count - 1 do
    IWTreeView1.Items [i].Expanded := True;
end;
   
procedure TformTree.EnlargeFont1Click(Sender: TObject);
begin
  IWTreeView1.Font.Size := IWTreeView1.Font.Size + 2;
end;

21.3 演示菜单、树形控件和动态创建组件的例程

感谢IntraWeb提供了如同标准Delphi VCL组件的特性,使代码易读,也容易理解。

 

例程中的菜单有两个子菜单稍微复杂一点。第一个是显示应用程序ID,也就是程序执行时的会话期ID。该标志可以通过全局对象WebApplication的AppID属性获得。第二个子菜单是Tree Contents,它可以把树形控件的一级节点标题和子节点数目清单列出。值得注意的是,这些信息显示在一个运行时才创建的组件memo里(见图21.3),这一点与在一个VCL应用程序里面做同样的事情非常相似。

procedure TformTree.TreeContents1Click(Sender: TObject);
var
  i: Integer;
begin
  with TIWMemo.Create(Self) do
  begin
    Parent := Self;
    Align := alBottom;
    for i := 0 to IWTreeView1.Items.Count - 1 do
      Lines.Add (IWTreeView1.Items [i].Caption + ‘ (‘ +
        IntToStr (IWTreeView1.Items [i].SubItems.Count) + ‘)‘);
  end;
end;
 
提示:请注意IntraWeb的alignment属性和VCL组件的alignment非常相似。比如程序菜单的alignment属性是alTop,而tree组件则是alClient,此外动态创建的memo的alignment属性被设为alBottom。作为替代方法,可以使用anchors(同样VCL中也有):可以创建一个bottom-right按钮,或者在页面中间的组件,只需把组件的四个anchors全设为true。请看下面关于该技术的例程。

Writing Multipage Applications

开发多页面应用程序

目前所讲的例程都只有一个页面,下面我们来创建IntraWeb程序的第二个页面。其实,就是这种情况,IntraWeb开发工具也与标准Delphi(或Kylix)十分相似,而与其他互联网开发工具十分不同。下面的例子可以通过IntraWeb向导自动产生源代码,接着研究我们关心的这些代码。

我们从头看,例程IWTwoForms的主窗体演示了IntraWeb表格特性。这是一个强大的组件,她产生的HTML表格既可放入文本又可放入其他组件。在本例中,程序开始运行时,填充表格的内容(在主窗体的OnCreate事件中处理):

procedure TformMain.IWAppFormCreate(Sender: TObject);
var
  i: Integer;
  link: TIWURL;
begin
  // set grid titles
  IWGrid1.Cell[0, 0].Text := ‘Row‘;
  IWGrid1.Cell[0, 1].Text := ‘Owner‘;
  IWGrid1.Cell[0, 2].Text := ‘Web Site‘;
  // set grid contents
  for i := 1 to IWGrid1.RowCount - 1 do
  begin
    IWGrid1.Cell [i,0].Text := ‘Row ‘ + IntToStr (i+1);
    IWGrid1.Cell [i,1].Text := ‘IWTwoForms by Marco Cantù‘;
    link := TIWURL.Create(Self);
    link.Text := ‘Click here‘;
    link.URL := ‘http://www.‘;
    IWGrid1.Cell [i,2].Control := link;
  end;
end;

上面这段代码的运行结果见图21.4,除了输出外,还有几件事值得注意。首先,表格使用了Delphi的anchors属性(全设为false)来使表格始终处在页面中间,即使用户改变了浏览器窗口大小。其次,我在第三列中加入了一个IWURL组件,当然也可以放其他组件(包括按钮和编辑框)。

21.4 例程IWTwoForms使用的表格组件嵌入文本和IWURL组件

第三,也是最值得研究的是IWGrid组件转换成了带框架和不带框架的HTML表格。这是表格中的一行HTML代码片断:

<tr>
  <td valign="middle" align="left" NOWRAP>
    <font style="font-size:10pt;">Row 2</font>
  </td>
  <td valign="middle" align="left" NOWRAP>
    <font style="font-size:10pt;">IWTwoForms by Marco Cantù</font>
  </td>
  <td valign="middle" align="left" NOWRAP>
    <font style="font-size:10pt;"></font>
    <a href="#" onclick="parent.LoadURL(‘http://www.‘)"
      id="TIWURL1" name="TIWURL1"
      style="z-index:100;font-style:normal;font-size:10pt;text-decoration:none;">
      Click here</a>
  </td>
</tr>
提示:在上面的代码清单中,我们注意到URL是通过JavaScript来激活链接的,而不是直接的超链接。由于IntraWeb允许客户端所有动作,比如确认、检查和提交,而这些动作都依赖于JavaScript。例如,如果你把一个组件的Required设成true,则该组件如果没有任何数据就不能提交,此时如果提交将会看到一个JavaScript错误信息(使用组件的FriendlyName属性来定制的消息框)。

本例的核心特性是它显示第二个页面的能力。为了实现这一点,首先需要给程序添加一个IntraWeb页,方法是单击File->New->Other…,启动Delphi的New Items对话框,翻到IntraWeb页,选择Application Form,单击“Ok”按钮完成添加工作。接着向该窗体上放一些组件,然后在主窗口中放置一个按钮或其他控件用来显示第二个窗体:

procedure TformMain.btnShowGraphicClick(Sender: TObject);
begin
  anotherform := TAnotherForm.Create(WebApplication);
  anotherform.Show;
end;

即使程序调用了Show方法,也会被看成是调用了ShowModal。这是因为IntraWeb把页面当成堆栈来处理。最后显示的页面在栈顶,同时显示在浏览器上。如果关闭该页(隐藏或销毁),就会显示该页的前一页。在本例中,第二页的关闭是通过调用Release方法,该方法在VCL程序中是结束正在运行的窗体的恰当方法。你也可以隐藏第二个窗体然后再显示它从而避免每次都重建窗体的实例。

警告:在例程中的主窗体上放置了一个Close按钮,但该按钮没有调用Release方法,而是调用了WebApplication对象的Terminate方法。该方法可以传递输出信息,如WebApplication.Terminate(‘goodbye’);例程中使用了另一种替换方法:TerminateAndRedirect。

现在已经知道如何创建带有两个窗体的IntraWeb程序,接着我们简要地考查一下IntraWeb是如何创建主窗体的。当创建一个新程序时,在项目文件里有由IntraWeb向导产生的相关代码:

begin
  IWRun(TFormMain, TIWServerController);

这一行不同于Delphi的标准项目文件,因为它调用了一个全局函数而不是应用全局对象的方法。函数的两个参数分别是主窗体的类和IntraWeb控制器的类。该控制器能够处理会话期和许多特性,稍后就会介绍。

例程中的第二个窗体显示了IntraWeb另外一个有趣的特性:图形支持。该窗体有一个显示雅典娜神像的图形组件,这是通过把一个位图装载进一个IWImage组件中实现的:Intraweb把这个位图转换成JPEG格式,并存到创建于程序所在文件夹内的cache文件夹中,然后再返回该JPEG文件的引用。其相应HTML代码如下:

<img src="/cache/JPG1.tmp" name="IWIMAGE1" border="0" width="153" height="139">
 

该例程使用的IntraWeb另外一个特性是用户可以用鼠标点击图像,并通过运行服务器端代码来实现修改图像的功能。在本例中,修改的结果是画绿色的小圆圈。

代码如下:

procedure Tanotherform.IWImage1MouseDown(ASender: TObject;
  const AX, AY: Integer);
var
  aCanvas: TCanvas;
begin
  aCanvas := IWImage1.Picture.Bitmap.Canvas;
  aCanvas.Pen.Width := 8;
  aCanvas.Pen.Color := clGreen;
  aCanvas.Ellipse(Ax - 10, Ay - 10, Ax + 10, Ay + 10);
end;
警告:绘制操作是发生在位图的画布(canvas)上。不要使用Image组件的画布(在VCL组件Image中是可以这样做的),也不要使用JPEG图像,否则不是没有响应就是出运行错误。

会话期管理

注:Session就是通话、话路。在打电话的时候,通常情况下每一对用户拥有一个话路,否则就会“窜线”了。在本章中,Session就是指客户端的一个用户和服务器交互的话路,或者称为交互通道。由于其他书籍中把Session译作“会话期”,这里沿用该译法。——译者。

如果你有一些Web编程经验,就会知道会话期管理是一个复杂的话题。IntraWeb提供预定义的会话期管理并且简化使用会话期的方法。如果在一个指定的窗体中需要会话数据,需要做的是给该窗体加一个域。IntraWeb窗体和组件会为每一个会话期创建一个实例。比如,在例程IWSession中,我给窗体添加一个域叫做FormCount,为了对比,我又在全局单元里声明一个全局变量GlobalCount,这个变量会被程序的所有实例所共享。

为了加强对会话数据的控制同时让多个窗体共享它,可以定制TuserSession类,该类是IntraWeb应用程序向导在ServerController单元中自动产生的。在例程IWSession中,我是这样定制的:

type
  TUserSession = class
  public
    UserCount: Integer;
  end;

IntraWeb 为每个新的会话期创建对象的实例,参阅ServerController单元中TIWServerController类的IWServerControllerBaseNewSession方法:

procedure TIWServerController.IWServerControllerBaseNewSession(
  ASession: TIWApplication; var VMainForm: TIWAppForm);
begin
  ASession.Data := TUserSession.Create;
end;

在代码中,会话期对象可以通过访问RwebApplication这个全局变量的Data域来引用,这个变量通常用来访问当前用户的会话期。

提示:RwebApplication是线程变量,在IWInit单元中定义。她提供了访问会话期数据的线程安全方法:在多线程环境下访问它需要倍加小心。该变量可以在窗体和控件之外使用(基于线程的),这就是为什么主要用在数据模块、全局程序和非IntraWeb类内的原因。

此外,默认的ServerController单元提供一个可用的辅助函数:

function UserSession: TUserSession;
begin
  Result := TUserSession(RWebApplication.Data);
end;

因为大多数代码已经自动产生了,像下面从例程IWSession中提取的代码那样,只需给TuserSession类添加数据,就可用通过UserSession函数简单地应用了。在例程中,单击按钮,程序会累加几个计数器(一个全局变量,两个会话期指定的)并通过标签显示它们的值:

procedure TformMain.IWButton1Click(Sender: TObject);
begin
  InterlockedIncrement (GlobalCount);
  Inc (FormCount);
   
  Inc (UserSession.UserCount);
   
  IWLabel1.Text := ‘Global: ‘ + IntToStr (GlobalCount);
  IWLabel2.Text := ‘Form: ‘ + IntToStr (FormCount);
  IWLabel3.Text := ‘User: ‘ + IntToStr (UserSession.UserCount);
end;

注意,程序通过调用Windows的InterlockedIncrement来避免被多线程所共享的全局变量发生访问冲突。也可以通过使用critical section或者是TidThreadSafeInteger(见于IdThreadsafe单元)来避免这种情况。

21.5显示了程序的输出(通过两个不同的浏览器创建两个会话期),程序还有一个复选框,用来激活计时器。听起来挺不可思议的,但实际上在IntraWeb程序中,计时器就和Windows中的计时器一样工作。当计时器的时间间隔到期时,相应的代码就会被执行。在网页中,这意味着触发JavaScript代码来刷新页面:

IWTIMER1=setTimeout(‘SubmitClick("IWTIMER1","", false)‘,5000);

21.5、运行在两个不同浏览器中的IWSession例程

WebBroker和WebSnap整合

到目前为止,只讲了如何创建stand-alone模式的IntraWeb应用程序。当你需要开发IIS或是Apache下的IntraWeb动态链接库时,情形也基本一样。但是,如果你想用IntraWeb技术来拓展已有的WebBroker(或是WebSnap)程序,情况就不一样了。

两种技术的桥梁是IWPageProducer组件。该组件像其他页生成器组件一样依附于WebBroker的action,同时可以使用一个特殊的事件来创建并获得一个IntraWeb窗体:

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

仅一行代码,就能实现IntraWeb页嵌入WebBroker程序,在例程CgiIntra中也是如此。IWModuleController对IntraWeb支持提供核心服务。每个IntraWeb项目都必须有这种组件才能正确地工作。

警告:Delphi7中发行的IntraWeb的IWModuleController组件和Delphi的Web App Debugger有冲突,但问题已经解决,可以免费更新。

这是例程的web module窗体摘要:

object WebModule1: TWebModule1
  Actions = <
    item
      Default = True
      Name = ‘WebActionItem1‘
      PathInfo = ‘/show‘
      OnAction = WebModule1WebActionItem1Action
    end
    item
      Name = ‘WebActionItem2‘
      PathInfo = ‘/iwdemo‘
      Producer = IWPageProducer1
    end>
  object IWModuleController1: TIWModuleController
  object IWPageProducer1: TIWPageProducer
    OnGetForm = IWPageProducer1GetForm
  end
end

因为这是一个页模式的CGI程序,所以没有会话期管理。此外,页面的组件状态不能像标准IntraWeb程序那样通过事件处理来自动更新。为了达到同样的效果,需要写一写特殊代码来进一步处理HTTP请求的参数。仅从这样一个简单例程就能看出页模式没有程序模式那么自动化,不过,页模式更灵活。尤其值得说的是,页模式给WebBroker和WebSnap程序增加了可视化设计的能力。

控制布局

例程CgiIntra还展示了另外一个非常有趣的IntraWeb技术:基于HTML的布局控制(页模式整合WebBroker和布局控制没有什么关系,因为在程序模式中也有布局控制,我只是为了省事才用一个例程来说明这两种技术的)。程序编译后的结果页面就是在设计时放到窗体上的一系列组件的映射,可以通过修改组件属性改变页面外观。一个页面上有很多内容,如文本框、按钮和图片等,这些内容如何分布,如何控制尺寸和位置?

解决的办法是使用IntraWeb的布局管理器。在IntraWeb程序中,总是要用到布局管理器。默认的布局管理器是IWLayoutMgrForm,另外两个是IWTemplateProcessorHTML和IWLayoutMgrHTML,前者使用外部的HTML模版文件,后者内嵌HTML。

IWLayoutMgrHTML组件包括一个功能强大的HTML编辑器,在这里你可以像放置普通HTML元素那样嵌入IntraWeb组件(在外部HTML编辑器里,你必须手动实现)。此外,当你从编辑器中选择一个IntraWeb组件时(双击IWLayoutMgrHTML组件即可启动该编辑器),你可以使用对象观察器来修改组件属性。如图21.6,IntraWeb的HTML布局编辑器是一个工具强大的可视化HTML编辑器,产生的HTML代码可以在另外一页看到(Source页)。

21.6:  IntraWeb HTML 布局编辑器

在产生的HTML代码中,定义了页的结构。组件是通过特殊标记:大括号来标识的,如下:

<P> {%IWLabel1%} {%IWButton1%}</P>

提示:当你使用HTML时,组件就不使用绝对位置定位了,而是由HTML而定。因此,此时的窗体仅仅是个组件容器,因为窗体中组件的位置和大小被忽略了。

不管怎么说,布局管理器总是能够满足程序在浏览器中运行时的外观需求。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多