Tivoli 服务台 6.0 开发工具包脚本程序设计指南

第 7 章:窗体系统

返回目录


介绍

定义

“TSD 脚本”提供用于从描述(资源)文件创建窗口的窗体系统。

窗体是包含多种数据项窗体的窗口。在 GUI 环境中,窗体是用户和应用程序之间主要的交互手段。开发人员从工具条中选择控件,将其放到空白窗体上。窗体控件包括:

窗体控件

窗体控件是用于从用户获得信息或向用户传送信息的组件。例如:一个数据项窗体通常包含一个或多个文本框、一个“确定”按钮和一个“取消”按钮。“开发工具包接口设计器”可用来向窗体添加控件。(请参见 Tivoli 服务台 6.0 开发工具包接口设计器指南了解其它信息)。

下面列表中包含“TSD 脚本”支持的所有窗体控件。

控件名 说明
子窗体 包含多个其他控件的综合控件。
文本框 允许用户输入单行信息的矩形区域。如果用户输入的文本一行放不下,则文本框自动卷动。
多行文本框 用于输入多行文本的矩形区域。可任选地使框中的文本环绕。
列表框 包含一列可能选择的矩形区域。用户不能在列表框中输入选择。
组合框 附带有一个列表框的文本框。用户可以向文本框中输入一个值或者在下拉列表中选择一个值。选择的值出现在文本框中,并且列表框消失。
显示分层数据的控件。
选项按钮 用于选择一个互斥选项集合中某一项的按钮。用户选择一个按钮,则此按钮就被填充。
复选框 其选项可被选中或清除以打开或关闭一个选项的方框。每次可以选择多个复选框。
滚动条 交互式移动的条。
按钮 启动某项操作的矩形按钮。
文本 显示文本的区域。用户不能修改这些文本。
时钟 运行时间时钟或占用时间计时器。
以行和列为结构的数据。
超文本 以超文本格式显示文本的区域。
组框 按意义或功能对多个控件进行分组的矩形框。
映像 从某文件显示图像的字段。

窗体文件

窗体保存为单独的应用程序资源。“开发工具包”允许创建一批窗体规格并将它们存储为以 .df 作后缀的文件。象知识库文件一样,这些规格包括一个源窗体和一个目标窗体。.df 文件允许菜单、工具条和字符串。

“接口生成器”是一个制作 .df 文件和创建对象 .dfc 文件的“TSD 脚本”程序。.dfc 文件由“开发工具包”在运行时间装入和显示。

样本窗体代码

下列 TSD 脚本代码段实例使用一个窗体。

  TYPES 
    EmployeeRecord IS RECORD 
      first, last, ssn : STRING; 
      salary : REAL; 
      department : STRING; 
 END; 
VARIABLES 
      employee: EmployeeRecord; 
   ACTIONS 
  IF DlgBox($Desktop,'EMPLOYEE.DFC[ADDFORM]',
            $NullHandler,employee) > 0 THEN 
        SQLInsert('EMPLOYEES',employee); 
 END; 

在这个实例中,一个新的 EmployeeRecord 类型在类型部分中声明。在变量部分,还有一个此种类型的变量。记录字段名与窗体控件名相同。

操作部分的 DlgBox 语句完成下列任务:

窗体通常还包括“确定”和“取消”按钮。

DlgBox 语句自变量

DlgBox 语句有 4 个自变量:

自变量标题 说明
父窗口 生成新窗体的父级窗口的句柄。
窗体文件 编辑的窗体规格文件名。如果文件包含多个窗体规格,则所要求的窗体名必须在文件名后用方括号括起来。
事件处理器 与以前讨论的类属窗口一样,所有的窗体都有一个与之相联系的事件处理器。

有时,可能需要处理器为每个事件执行缺省操作。在这些情况下,可以
指定 $NullHandler。此时,$NullHandler 允许用户从一个窗体控件移到另一个窗体控件
并可向窗体中输入值。

当用户选择具有“接受”属性的按钮时,TSD 脚本将自动把窗体控件中的内容复制到
结果变量中的对应字段。

结果变量 其字段与窗体中的控件相对应的记录变量。

当用户按下具有“接受”属性的按钮退出窗体时,该窗体上每个控件的内容都被复制到
记录变量的对应字段中。然后该记录变量可以写进数据库,显示到一个
窗口,或者任何对于应用程序合适的地方。

DlgBox 实例

考虑另一个实例:

  TYPES 
    EmployeeRecord IS RECORD 
      first, last, ssn : STRING; 
      salary : REAL; 
      department : STRING; 
 END; 
VARIABLES 
      employee: EmployeeRecord; 
   ACTIONS 
  SQLSelectInto('SELECT * FROM EMPLOYEES WHERE 
              SSN=305-33-4111',employee); 
  IF DlgBox($Desktop,'EMPLOYEE.DFC[EDITFORM]',
            $NullHandler{employee},employee) >> 0 THEN 
    SQLUpdate('EMPLOYEES','WHERE SSN=''' & 
            employee.snn & '''',employee); 
 END; 

该实例程序代码可以实现下列任务:

对这个 DlgBox 语句已做了两处修改:

本例中,用户可以在窗体中看到从 EMPLOYEES 表检索到的信息,并且可以移动到任何窗体以及更改任何信息。

窗体事件处理器

为了处理高级功能,比如在用户选择一个按钮时显示一个员工的照片或验证一个社会安全号的格式,必须使用事件处理器。要做到这一点,需要生成窗体事件处理器。

事件处理器实例

本节介绍了一个带有事件处理器的窗体。该实例展示了一个完整的名为 Employees 的知识库,它实现名为 AddEmployee 的单一公用函数。 AddEmployee 的主体与前面的实例类似,除了该实例没有使用 $NullHandler 而引用了一个名为 EmployeeEvent 的事件处理器。

KNOWLEDGEBASE Employees; 
  USES 
  Globals; 
  TYPES 
    EmployeeRecord IS RECORD 
      first, last, ssn : STRING; 
      salary : REAL; 
      department : STRING; 
 END; 
    ROUTINES 
    FUNCTION AddEmployee: BOOLEAN; 
PRIVATE 
    ROUTINES 
    EVENT EmployeeEvent(REF employee: 
                        EmployeeRecord) IS 
    ROUTINES 
      FUNCTION ValidSSN(VAL ssn: STRING): BOOLEAN IS 
VARIABLES 
        i: INTEGER; 
   ACTIONS 
        IF StrLength(ssn) <> 11 THEN 
        EXIT(FALSE); 
 END; 
        FOR i:=1 TO 11 DO 
          IF (i = 4 OR i = 7) AND (ssn[i] <> '-') THEN 
        EXIT(FALSE); 
          ELSIF StrPos('0123456789',ssn[i]) = 0 THEN 
        EXIT(FALSE); 
 END; 
 END; 
        EXIT(TRUE); 
      END (* Valid SSN *); 
       ACTIONS 
WHEN $Event IS $MsgSelect THEN 
        WHEN $FieldName IS 'SSN' THEN 
          IF NOT ValidSSN(employee.ssn) THEN 
            Exit(0); 
 END; 
        ELSWHEN 'PICTURE_BUTTON' THEN 
          ShowPicture(employee.last_name & '.BMP'); 
 END; 
 END; 
    END (* Employee Event *); 
    FUNCTION AddEmployee: BOOLEAN IS 
VARIABLES 
      employee: EmployeeRecord; 
   ACTIONS 
      IF DlgBox(mainWindow, 'EMPLOYEE.DFC[ADDFORM]',
                EmployeeEvent{employee},employee) > 0 THEN
        SQLInsert('EMPLOYEES',employee); 
        EXIT(TRUE); 
      ELSE 
        EXIT(FALSE); 
 END; 
    END (* Add Employee *); 

EmployeeEvent 是一个采用单个引用传递参数的事件处理器,此参数与在 DlgBox 中传递的返回变量的类型相同。

该事件处理器只测试一个事件 $MsgSelect,并且每当窗体要把光标从当前控件中移出时产生该事件。

如果用户向一个文本控件中输入一个值并按下 TAB 键,就会产生一个 $MsgSelect 事件。用户要离开的控件名和该事件一起出现在一个名为 $FieldName 的“不可见”参数中。

下一个实例更接近 EmployeeEvent 的主体。

WHEN $Event IS $MsgSelect THEN 
        WHEN $FieldName IS 'SSN' THEN 
          IF NOT ValidSSN(employee.ssn) THEN 
            Exit(0); 
 END; 
        ELSWHEN 'PICTURE_BUTTON' THEN 
          ShowPicture(employee.last_name & '.BMP'); 
 END; 
 END; 

该实例说明:

缺省结果为“1”,表示成功。但是有时需要返回不同的值。

$MsgSelect 事件

当事件处理器退出并且返回值为 0 时,不接受“TSD 脚本”自动产生的某些事件。$MsgSelect 就是这样的事件。

如果 EmployeeEvent 在为 SSN 字段处理 $MsgSelect 事件时发现了一个无效的社会安全号,则退出并返回 0 值。

这种情况被认为是拒绝事件。拒绝的结果是双重的。

产生 $MsgSelect 事件

通常,$MsgSelect 事件让用户知道窗体中的某些东西已经改变。 $MsgSelect 可以通过下述三种方式之一产生:

注:只有在新值与旧值不同时才产生 $MsgSelect

注:如果定义了缺省命令按钮,则按下回车键和选择缺省命令按钮的作用是相同的。这将产生一个 $MsgAccept 事件。如果没有缺省命令按钮,将产生一个 $MsgSelect 事件。

当事件处理器接收到 $MsgSelect 事件时,窗口实例数据(事件处理器以其记录自变量引用它)将更新以反映更改。例如,当用户向 SSN 文本框中输入值并按下 TAB 键时,该值即被拷贝到窗口实例变量的 SSN 字段并产生一个 $MsgSelect 事件。以前的字段值在第一个未命名的事件参数中可得到。

Select 消息完成之前,控件的值不定义;因此不能查询控件值。

其它窗体事件

窗体可以产生许多其它事件,包括:

窗体事件 说明
$MsgInitialize 特殊型的 $MsgSelect,仅在窗体的创建阶段产生。
$MsgCreate 在窗体显示前收到该事件。此时适于执行初始化,如向列表框添加
可能的选择列表等等。
$MsgDestroy 在窗体关闭前收到该事件。
$MsgAccept 当用户接受窗体时收到该事件,通常用户通过按下回车键或选择“确定”来接受窗体。
$MsgCancel 当用户取消窗体时收到该事件,通常用户通过按下 ESCAPE 键或选择“取消”来取消窗体。
$MsgEnterField 当光标正要指定一个新控件时收到该事件。 $FieldName 中含有新控件的
名字。
$MsgExitField 当光标正要离开一个控件时收到该事件。 $FieldName 包含该控件的名字。
$MsgHelp 当用户选择“帮助”或按下 F1 键时收到该事件。
$MsgMandField 当窗体中的一个或多个必需文本输入框没有填,而用户就试图接受该窗体时,将收到该事件。

$FieldName 包含第一个空的必需文本输入框的名字。缺省情况下,系统显示
一条消息将问题通知用户。返回 0 阻止显示此框。

窗体控件名

窗体上的每个控件都有一个名字。在前面的例子中,一个窗体用来收集填充一个 EmployeeRecord 类型变量所需的信息。由于该记录有个名为 FIRST_NAME 的字段,所以也需要一个名为 FIRST_NAME 的窗体控件。当用户向 FIRST_NAME 窗体控件中输入值时,输入的信息被拷贝到 FIRST_NAME 记录字段。

注:有些控件不带数据。例如,命令按钮没有值,它们产生事件。因此不是窗体上的每个按钮都需要一个记录字段。

附加的控件属性

可以为窗体控件指定附加的属性,包括:

属性 说明
只读 控件中的数据由窗口实例记录初始化,并且不能被用户修改。
必需 只有为所有必需的控件都提供了值后用户才能接受窗体。
输入长度 指定用户可以在文本字段中向控件输入的字符数。

还有其它一些只影响特定控件的属性。例如,可以启用或关闭多行文本框的字环绕。

说明

是用来查看 SQL 结果表的窗口。一个 SQL 结果表是一些行和列的集合。

被用作一个窗体控件,并允许:

中的列是可以改变尺寸的。一条细竖线隔开相邻的两列,用户可以通过改变线的位置来改变列宽。

选择语句可以在 .df 文件中指定或编程指定。

语句 说明
DlgSQLSelect 该语句引起“TSD 脚本”发出指定的 SQL 查询并用查询结果刷新指定控件的内容。

该语句有三个自变量:

  • 窗体的窗口句柄
  • 控件名
  • 代表 SQLSelect 语句的字符串表达式

这是为表控件从数据库中取得数据的最有效的方法。

DlgFieldValue 该语句可用来检索选定的行。
该语句有三个自变量:
  • 窗体窗口句柄
  • 控件名
  • 从突出显示行接收信息的记录变量

行的列被拷贝到有相同名字(如“FIRST_NAME”列拷贝到 r.FIRST_NAME)的记录字段中。

DlgListBoxInsert 该语句向中插入一个新行。该命令不执行 SQLInsert 语句,而是向指定的窗体控件添加一个新行。

该语句有三个自变量:

  • 窗体窗口句柄
  • 控件名
  • 其字段和中的列名匹配的记录变量

匹配的值拷贝到相应的列中,而没有列匹配的记录字段被忽略。

DlgListBoxUpdate 该语句更新中选定的行。该命令不执行 SQLUpdate 语句,但更新窗体中的信息。

该语句有三个自变量:

  • 窗体窗口句柄
  • 控件名
  • 其字段和控件中的列名匹配的记录变量

匹配的值拷贝到恰当的列中。没有列匹配的记录字段被忽略。

DlgListBoxDelete 该语句删除控件中选定的行。该命令不执行 SQLDelete 操作,但从窗体窗口中的指定控件中移去一行。

该语句有两个自变量:

  • 窗体窗口句柄
  • 控件名

表例子

该实例创建一个名为 Users 的知识库,它带有一个叫 WorkWithUsers 的单一公用过程。

KNOWLEDGEBASE Users; 
  TYPES 
    UserRecord IS RECORD 
      $Select : String; 
      user_ID : String; 
      user_name : String; 
      user_rights : Integer; 
 END; 
    ROUTINES 
    PROCEDURE WorkWithUsers; 
PRIVATE 
    ROUTINES 
    EVENT UserEvent(REF user: UserRecord) IS; 
VARIABLES 
      i: Integer; 
    ROUTINES 
      PROCEDURE AddUser IS; 
VARIABLES 
        newUser: UserRecord; 
   ACTIONS 
        IF DlgBox($Desktop,'USERS.DFC[ADDFORM]',$NullEvent,
           newUser) > 0 AND 
           SQLInsert('USERS',newUser) > 0 THEN
           DlgListBoxInsert($Handle,'USERLIST',newUser); 
 END; 
     END (* Add User *); 
     PROCEDURE EditUser IS; 
   ACTIONS 
       IF DlgFieldValue($Handle,'USERLIST',user) 
          > 0 AND
          DlgBox($Desktop,'USERS.DFC[ADDFORM]',$NullEvent
         {user},user) > 0 AND
         SQLUpdate('USERS','USER_ID=''' 
          user.user_ID & '''',user) > 0 THEN 
          DlgListBoxUpdate($Handle,'USERLIST',user);
 END; 
     END (* Edit User *); 
     PROCEDURE DeleteUser IS; 
   ACTIONS 
       IF DlgFieldValue($Handle,'USERLIST',user) > 0 AND
          SQLDelete('USERS','USER_ID='''&user.user_ID&'''')
              > 0 THEN
          DlgListBoxDelete($Handle,'USERLIST',user);
 END; 
     END (* Delete User *); 
      ACTIONS 
     WHEN $Event IS $MsgCreate THEN 
       DlgSQLSelect($Handle,'USERLIST',user.$select);
     ELSWHEN $MsgSelect THEN 
       WHEN $FieldName IS 'ADD_BUTTON' THEN 
         AddUser; 
       ELSWHEN 'EDIT_BUTTON' THEN 
         EditUser; 
       ELSWHEN 'DELETE_BUTTON' THEN 
         DeleteUser; 
 END; 
 END; 
   END (* User Event *); 
   PROCEDURE WorkWithUsers IS; 
VARIABLES 
     UserWindow: WINDOW; 
     user: UserRecord; 
   ACTIONS 
     user.$select = 'SELECT * FROM USERS'; 
     DlgCreate($Desktop,userWindow,
               'USERS.DFC [WORKWITHUSERS]',
               UserEvent{user}); 
   END (* Work With Users *); 

实例解释

WorkWithUsers 的作用是创建一个带有下列控件的窗体:

窗体的 UserEvent 事件处理器处理下列事件:

只保留其列说明所指定的信息。它可能是包含在 SQL 结果表中的列的子集。当使用 DlgFieldValue 命令从控件中检索行时,只返回和控件中列相对应的字段。为了完成余下的记录,可能需要执行 SQLSelectIntoSQLSelect

创建窗体

“TSD 脚本”创建一个新窗体的进程包括下列几个步骤:

注:记录实例变量中的数据将覆盖窗体文件提供的初始值。

模态窗体

模态窗体是一种在继续进行前程序等待用户接受或者取消的窗体。当显示模态对话框时,不能选择其它的窗口。

模态窗体是用 DlgBox 创建的。在用户结束 DlgBox 创建的窗体前,不会执行其后面的语句。用户指定的信息由第四个自变量返回到 DlgBox。这是输出记录变量。

模态窗体应该主要用于重要的错误消息,或用户在没有回答询问之前不能继续的关键对话框。有关文件删除的消息可能就是一个此类窗体的例子。

非模态窗体

非模态窗体是一种应用程序在继续执行前不需等待用户的窗体。这意味着在显示该窗体时用户可以切换到其它的窗口。

非模态窗体由 DlgCreate 创建。当调用 DlgCreate 时,创建窗体的进程就被启动。但是,下一条语句的执行也同时发生。

新窗体有自己的用户界面和自己的程序(事件处理器)。它继续存在,直到用户接受或取消窗体或者应用程序的其它部分发送一条( $MsgClose)消息为止。

注意:在事件驱动的程序设计中,首选非模态窗体。

标签窗体

“TSD 脚本”提供一种带有“页”标签的特殊窗体。用户可以通过选择标签从某一页移动到另一页。

用户可以在“开发工具包接口设计器”中通过指定要合并的一个或多个窗体来创建标签窗体。在运行时,可以象使用其它类型窗体一样使用这些窗体。它们可以用 DlgBoxDlgCreate 来创建。要管理它们的事件,可以创建一个事件处理器。

当处理标签窗体时,请记住下列事项:


Tivoli 服务台 6.0 开发工具包脚本程序设计指南

返回目录

版权所有