1、第10章 数据窗口高级技术 10.1 概述 数据窗口对象主要用于操作数据库中的数据,它不仅为数据的增加、删除、修改、更新和查询等数据库操作提供了图形化接口,而且还可以指定数据的输入格式、输出格式以及数据的显示风格。此外,在PowerBuilder 7.0以后的版本中,用户还可以在数据窗口对象中增加多种对象(包括按钮、静态文本框、图片等)。 应用程序中使用的数据窗口通常由数据窗口对象和数据窗口控件两部分组成。数据窗口控件是粘贴到窗口上的一个对象,与OLE控件有点类似;数据窗口对象是粘贴到数据窗口控件或数据存储中的对象,它通过数据窗口画笔来创建,并保存到应用库中。通
2、过数据窗口对象与数据窗口控件的配合使用,来完成数据的显示、增加、删除、修改等操作。 创建数据窗口的一般步骤为: (1) 使用数据窗口画笔创建数据窗口对象,并把它保存到PowerBuilder应用库中。创建数据窗口对象的操作一般包括下述内容:定义数据源、选择数据窗口的表现风格、设置数据窗口对象及该对象内其他对象的属性(例如显示格式、编辑风格、跳转次序、有效性规则、排序与检索条件)等。如图10-1所示。 图10-1 数据窗口对象的创建 (2) 在窗口或用户对象中建立一个数据窗口控件,如图10-2所示。 图10-2 创建数据窗口控件 (3) 设置数据窗口控件的属性或编写代码,
3、建立数据窗口控件与数据窗口对象的关联。 (4) 针对具体应用,编写数据窗口控件的事件处理程序,如显示数据、响应用户操作。 考虑到本书的读者对PowerBuilder已经有了一定的了解,这里只给出了创建数据窗口的大致步骤,具体细节请参阅PowerBuilder的入门书籍或者帮助文件。 第10章 数据窗口高级技术 10.2 数据窗口控件的重要属性、事件和函数(1) 与其他控件相似,数据窗口控件也是放置在窗口或用户对象上的一个控件。数据窗口控件的属性、事件和函数的数量相当庞大,这里主要介绍一些不容易掌握的属性、函数和事件。 10.2.1 数据窗口控件的重要属性
4、 在PowerBuilder的可视化界面中,可以设置数据窗口控件的绝大部分属性,多数属性的作用从属性名称中就可以判断出来,但是有些属性的作用却不容易判断,例如:DataObiect、DragAuto等,此处主要介绍一下这些属性的作用。 (1) DataObject属性 String类型,指定与数据窗口控件相关联的数据窗口对象名或报表对象名。 比如代码中使用语句dw_1.DataObject = 'd_zuozhe',可将数据窗口对象d_zuozhe显示在数据窗口控件dw_1中。这在创建动态数据窗口时经常用到。 (2) DragAuto属性 Boolean类型,指定PowerBuil
5、der是否自动把数据窗口控件置入拖曳模式(Drag Mode)。有效取值为:True,当数据窗口控件被单击时,数据窗口控件自动进入拖曳模式;False,当数据窗口控件被单击时,数据窗口控件不自动进入拖曳模式。此时,如果需要让数据窗口控件进入拖曳模式,需要在代码中使用Drag()函数手工设置。 (3) Object属性 DWObject类型,用于在代码中直接操作数据窗口对象中的对象,包括设置对象的属性、得到数据窗口中的数据等。数据窗口对象中的对象包括:列对象、文本对象、图像对象、按钮对象、Datawindow对象等。 (4) 示例 例如,放置了数据窗口dw_zuozhe的窗口w_test
6、如图10-3所示。 图10-3 更改数据窗口属性前 在窗口的open事件中添加代码: dw_1.Object.s_zuozhexingming_t.text="修改后的姓名编码" 显示的变化如图10-4所示。 图10-4 更改数据窗口属性后 10.2.2 数据窗口控件的重要事件 数据窗口控件的事件很多,这里主要从如何利用事件进行应用开发的角度对数据窗口控件的事件分类介绍并给出部分实例。当然,本书对事件的分类并不是绝对的。对于一些比较容易的事件,例如Clicked事件等,这里就不再赘述。 1. 用于触发数据窗口内部控件的事件 PowerBuilder的数据窗口提供
7、了用于触发内部控件的事件,这些事件主要用于数据窗口内的按钮控件,下面分别介绍: (1) ButtonClicking事件 ButtonClicking事件在单击数据窗口内的按钮对象时触发。触发的条件是该按钮的SuppressEventProcessing属性设置为no。该事件在ButtonClicked事件之前、Clicked事件之后触发。该事件在系统处理按钮的默认动作前触发。返回值的意义为:0,继续处理;1,不执行按钮的指定动作,但仍会接着触发ButtonClicked事件。 返回的参数包括: ● row:长整形,用户单击的行号。 ● Actionreturncod
8、e:长整形,该事件返回的动作代码。 ● dwo DWObject:指针类型,指向用户单击的对象。 (2) ButtonClicked事件 当数据窗口内的按钮对象的SuppressEventProcessing属性设置为no后,单击该按钮时触发ButtonClicked事件。该事件在系统处理完按钮的默认动作后触发。 返回的参数包括: ● row:长整形,用户单击的行号。 ● dwo DWObject:指针类型,指向用户单击的对象。 (3) 示例 在dw_1的Buttonclicking的事件上添加代码: dw_1.Object.s_xiaozhu
9、an_t.text="触发buttonclicking事件后的小传" 单击数据窗口中的【确定】按钮后可以看见窗口内容的变化,如图10-5所示。 图10-5 Buttonclicking事件演示 2. 用于处理数据窗口错误的事件 要使应用程序具有良好的容错性,处理好数据窗口的错误事件至关重要。下面分别介绍常用的数据窗口错误事件。 (1) DBError事件 当数据窗口控件访问数据库时发生数据库错误则触发该事件。该事件返回值的意义为:0,默认值,系统显示出错信息;1,系统不显示出错信息。可以利用该事件进行数据窗口的错误处理。在这个事件中,可以编写自己的出错处理程序,以提高程序的容
10、错性。 该事件的参数为: ● sqldbcode:长整数类型,包含由数据库厂商提供的特定出错代码,代码含义可以参见数据库厂商提供的有关文档。如果数据库厂商未提供出错代码,则sqldbcode值的意义如表10-1所示。 表10-1 sqldbcode值的意义 sqldbcode值 意 义 –1 不能连接到数据库(可能是因为事务对象中未正确提供某些参数) –2 不能连接到数据库 –3 Update或Retrieve中指定的键值与现有行不匹配 –4 写Blob型数据时发生错误 ● sqlerrtext:字符串型,数据库厂商提供的错误消息文本。
11、 ● Sqlsyntax:字符串型,发生错误的SQL语句的全部代码。 ● Buffer:数据窗口缓冲区,错误发生时数据行所在的缓冲区。它的取值为Delete!、Filter!或Primary!。 ● Row:长整型数,在对数据行进行UPDATED、SELECTED、INSERTED或DELETED操作时发生错误的数据行号。 例如,在DBError事件中可以编写如下脚本: CHOOSE CASE sqldbcode CASE -4 //写Blob数据类型时出错。 MessageBox("Error","出错行在"+string(row)+ "写Blo
12、b数据时出错") CASE…… …… //其他出错代码 END CHOOSE RETURN 1 //隐藏系统出错消息窗口 (2) Error事件 Error事件当数据窗口对象的数据或属性表达式发生错误时触发。 该事件的参数为: ● errortext:字符串型,PowerBuilder的出错消息文本。 ● errornumber:无符号整型数,PowerBuilder的出错信息编号。 ● errorwindowmenu:字符串型,引起错误的窗口或菜单名。 ● errorobject:字符串型,引起错误的对象。 ● er
13、rorline:无符号整型数,发生错误的行号。 ● errorscript:字符串型,引起错误发生的脚本。 ● action:ExceptionAction,该参数指定执行完Error事件中的脚本以后,应用程序要做的相应工作。该参数的取值如表10-2所示。 表10-2 ExceptionAction参数取值 参 数 取 值 意 义 ExceptionFail! 触发SystemError事件 ExceptionRetry! 如果是OLE服务器没有准备好,重新执行函数或检查表达式,该选项对数据窗口控件不适用 ExceptionIgnore 忽略发生的
14、错误(使用该参数时要小心,忽略当前错误可能会引起其他错误) ExceptionSubstituteReturnValue! 取消错误条件并使用returnvalue指定的值代替OLE服务器或数据窗口返回的值 ● Returnvalue:Any型(Any型可以保存各种数据类型,包括标准数据类型、对象、结构等,但是它不能用于EAServer的组件定义),用于ExceptionSubstituteReturnValue!选项的返回值。 例如,在Error事件中编写以下脚本(该脚本将在报错后触发SystemError事件): MessageBox("错误号:"+string(e
15、rrornumber),"错误为:"+String(errortext)) Action= ExceptionFail! 对于数据窗口控件来说,如果正在运行数据或属性表达式时发生错误,且Error事件中没有脚本,或者参数action被置为ExceptionFail!,则PowerBuilder首先触发Error事件,然后SystemError事件被触发;如果SystemError事件中也没有脚本,应用程序发生错误并终止运行。 10.2 数据窗口控件的重要属性、事件和函数(2) (3) ItemError事件 该事件在用户修改了字段,然后移走焦点,但数据未能通过该列的
16、有效性检查时触发。 该事件返回值的意义如下。 ● 0:(默认值),拒绝输入值并显示有效性检查出错信息,同时不允许移走焦点。 ● 1:拒绝输入值,但不显示出错信息,同时不允许移走焦点。 ● 2:接收输入值。 ● 3:拒绝输入值,但允许移走焦点。 它的参数包括: ● row:长整数型,表示数据行号。该行即发生改变但没有通过有效性检验的字段的行号。 ● dwo:dwobject,发生错误的数据窗口对象。 ● data:字符串型,新输入的发生改变的项的数据。 例如,在ItemError事件中添加如下脚本,则除了长整数类型的字段
17、可以为空外,不允许数据窗口控件中的其他字段为空,系统自动检查这些字段并为其赋值。 string str_colname,str_datatype str_colname=dwo.Name str_datatype:dwo.ColType IF str_datatype<>"long" THEN IF trim(data) = ' ' THEN RETURN 0; ELSE IF trim(data) = ' ' THEN This.Setltem(row,str_colname,0) END IF 3. 用于开发拖曳功能的事件 当需要把一个数据窗口中的数据移到另一个数据窗
18、口时,使用拖曳的方式更符合用户的习惯。开发数据的拖曳功能必须用到以下4个事件。 ● DragDrop事件:当某个被拖曳控件放置到数据窗口控件上时触发。 ● DragEnter事件:当某个被拖曳控件进入数据窗口控件时触发。 ● DragLeave事件:当某个被拖曳控件离开数据窗口控件时触发。 ● DragWithin事件:当某个被拖曳控件处于数据窗口控件内部时触发。 例如,编写一个拖曳程序,当拖曳作者列表数据窗口(dw_2)到作者显示数据窗口(dw_1)时,dw_1显示拖曳来的作者信息。步骤如下: (1) 在窗口中增加实例变量rownum。 (2)
19、设置dw_2的drag属性为“假”。 (3) 在dw_2中增加用户事件of_lbuttondown,映射到系统事件PBerm_lbuttondown。并在该事件中增加代码: dw_2.dragicon ='Form!' dw_2.drag(begin!) (4) 在dw_2的clicked事件中增加代码: dw_2.selectrow(row,true) rownum = row (5) 在dw_1数据窗口的DragEnter事件中增加代码: dw_1.retrieve(rownum) 这就可以实现拖曳的显示效果了。读者可以仿照该例编写其他程序。 4. 处理数据窗口变化的事
20、件 当用户在数据窗口控件中变换焦点或者输入字符时将触发数据窗口的EditChanged、ItemChanged或者ItemFocusChanged事件,下面分别介绍。 (1) EditChanged事件 EditChanged事件在用户在数据窗口控件的编辑控件中按任意键时触发。返回值为0,表示继续处理。 它的参数包括: ● row:长整数型,表示数据行号。即发生改变的行号。 ● dwo:dwobject,发生错误的列控件,注意,并不是指列名。 ● data:字符串型,新输入的发生改变的项的值。 (2) ItemChanged事件 ItemChanged
21、事件在数据窗口控件中的某个域被修改并且该域失去输入焦点(比如,用户按下了Enter键、Tab键或箭头键,或用户单击了数据窗口中其他域)时触发。 该事件返回值的意义为: ● 0:(默认返回值)接受新修改的值。 ● 1:不接受新修改的值且不允许改变输入焦点。 ● 2:不接受新修改的值但允许改变输入焦点。 参数含义为: ● row:表示发生改变的项所在的行号。 ● dwo:对拥有改变数据的字段对象的引用。 ● data:以字符串表示的改变项的新数据。 可在该事件中编写用户自定义的附加检验规则。 (3) ItemFocusChange
22、d事件 ItemFocusChanged事件在焦点从一个可编辑字段切换到另一个可编辑字段时触发。包括第一次显示数据窗口。参数row表示获得焦点的数据行,dwo表示获得焦点的字段对象。在ItemFocusChanged事件中,dwo总是字段对象,因此,用户可以通过字段对象的其他属性获得更多的信息,例如dwo.zuozhe和dwo.xingming属性等。 10.2 数据窗口控件的重要属性、事件和函数(3) 5. 用于打印数据窗口的事件 打印数据窗口时将触发数据窗口的打印事件,这些事件主要有以下这些。 (1) PrintEnd事件 PrintEnd事件在数据窗口打印结
23、束后触发。 (2) PrintPage事件 PrintPage事件在每页数据格式化打印之前触发。该事件返回值的意义为:0,打印当前页;1,跳过当前页。该事件提供以下参数。 ● pagenumber:长整数型,要打印的页号。 ● copy:要打印的拷贝。 (3) PrintStart事件 PrintStart事件在开始打印数据窗口之前发生。参数pagesmax表示打印的页数,该事件的返回值为长整数型,返回0时表示继续执行应用程序。如果需要忽略打印数据窗口或数据存储对象中某些页的数据时,可以在PrintPage事件中编写脚本。 具体实例将在第11章报表/图表打印的高级
24、设计中讲述。 6. 用于修改数据窗口默认处理方式的Other事件 该事件在发生了某个Windows消息,而该消息又不对应于该控件的某个PowerBuilder事件时触发。例如,在数据窗口中常使用滚动条,在默认状态下,单击垂直滚动条时,当前的数据窗口滚动显示一页或一行新内容,但是如果希望单击滚动条时,系统有另外的响应,这时就会用到Other事件。 例如,当有两个数据窗口,一个用来显示列表(dw_list),一个用来显示列表当前行的详细信息时(dw_detail),用户希望在列表中单击列表的垂直滚动条时,列表窗口只向下滚动一条记录,而且详细信息的显示也随之变化,这时可以利用Other事件来实
25、现。具体实例参见10.6节数据窗口事件处理技术。 7. 数据窗口的检索和更新事件 检索或更新数据窗口时将触发数据窗口的检索和更新事件,这些事件包括: (1) RetrieveStart事件 RetrieveStart事件在数据窗口开始检索数据时触发。该事件返回值的意义为: ● 0:(默认值)继续检索。 ● 1:终止检索。 ● 2:从数据库中检索数据前不清除原有数据及缓冲区。 例如,可以在RetrieveStart事件中编写以下脚本,控制检索权限,即只有特定标识号的用户才可以具有检索权限。 CHOOSE CASE user_id CASE IS<10
26、 RETURN 1 CASE 10 TO 20 RETURN 0 CASE IS>20 RETURN 1 END CHOOSE 当然,控制权限的代码只有放在服务器上才能真正有效。 (2) RetrieveRow事件 RetrieveRow事件在数据窗口每检索一条记录时触发。该事件返回值的意义为: ● 0:(默认值)继续随后的检索。 ● 1:终止检索过程。 当需要限制检索出的数据行数或其他条件时,可以使用RetrieveRow事件的返回值1终止检索。 要注意,当使用该事件检索大量数据时会明显影响到应用程序的性能。 例如,在RetrieveRow事
27、件中编写如下脚本以防止检索出超过限制的数据行数。 IF row>50 THEN MessageBox("STOP!","已经检索50条记录") RETURN 1 ELSE RETURN 0 END 1F (3) RetrieveEnd事件 RetrieveEnd事件在当数据窗口检索完数据后触发。 (4) Updatestart和UpdateEnd事件 当数据窗口更新数据库后触发UpdateEnd事件。在调用Update()函数后、修改数据库数据前触发UpdateStart事件。该事件返回值的意义如下。 ● 0:(默认值)继续更新。 ● 1:不执行
28、更新。 UpdateEnd事件提供以下参数。 ● argument:参数描述。 ● rowsinserted:长整型数,更新操作中新插入数据库的行数。 ● rowsupdated:长整型数,更新操作中被更新的行数。 ● rowsdeleted:长整型数,更新操作中被删除的行数。 (5) SQLPreview事件 该事件在调用Retrieve()、Update()或ReselectRow()函数后,SQL语句被发送到DBMS前发生。由Update()函数触发该事件时,该事件返回值的意义为:0,继续更新;1,停止更新;2,跳过本次请求继续执行。 该事
29、件提供以下参数。 ● request:SQLPreviewFunction类型,表示要求访问数据库的函数类型。它的取值如下。 ♦ PreviewFunctionReselectRow!:ReselectRow()函数。 ♦ PreviewFunctionRetrieve!:Retrieve()函数。 ♦ PreviewFunctionUpdate!:Update()函数。 ● sqltype:SQLPreviewType类型,指发送到DBMS的SQL语句的类型,它的取值如下。 ♦ PreviewDelete!:DELETE语句。 ♦ Previewlnsert!:
30、INSERT语句。 ♦ PreviewSelect!:SELECT语句。 ♦ PreviewUpdate!:UPDATE语句。 ● sqlsyntax:字符串型,全部SQL语句的文本。 ● buffer:DWBuffer类型,与数据库操作有关的包含数据行的缓冲区。 ● row:长整数型,将要被更新、插入、选择或删除的数据行。 用户可以使用sqlsyntax参数修改将要执行的SQL语句,例如,可以通过获得sqlsyntax参数获得语句,修改以后调用SetSQLPreview函数,再将SQL语句发送给DBMS。 若用户在数据库描述中设置了绑定选项,sqlsyn
31、tax参数得到的SQl语句就可能不完全,绑定的变量没有被实际的变量所代替,而是以问号的形式出现。所以,如果需要SQL语句的完全语法,应该取消数据库的绑定设置。方法是,打开DatabaseProfile Setup对话框,选择Transaction选项卡,取消选择Disable Bind复选框。 10.2 数据窗口控件的重要属性、事件和函数(4) 10.2.3 数据窗口控件的重要函数 数据窗口控件的函数很多,使用起来也非常灵活。为便于查阅使用,本章将按使用方法分类介绍数据窗口控件的重要函数。 1. 用于数据库操作的函数 PowerBuilder的数据窗口控件提供
32、了用于检索、更新、插入、删除数据库中数据的函数,下面分别介绍。 (1) Retrieve()函数 Retrieve()函数的调用格式为: dwcontrol.Retrieve ( {, argument, argument . . . } ) 其中,dwcontrol为数据窗口控件名;argument为向数据窗口对象的SQL SELECT语句提供的检索参数。 Retrieve()函数使用指定的数据窗口控件从数据库中提取数据。如果为该函数提供了参数,那么这些参数的值将用作数据窗口对象的SQL SELECT语句的提取参数。 Retrieve()函数的返回值为Long数据类型。函数执行成
33、功时,返回显示在数据窗口中的数据行的行数(即主缓冲区的数据行数);函数执行失败时返回-1。如果任何参数的值都为NULL,则返回NULL。 使用Retrieve()函数检索数据时,系统自动执行数据窗口对象的过滤条件,不满足过滤条件的行被立即移动到过滤缓冲区中,Retrieve()函数返回的行不包括移动到过滤缓冲区中的行。在执行Retrieve()函数之前,必须用数据窗口控件的对象函数SetTransObject()为数据窗口控件设置事务对象。当使用SetTransObject()函数时,在调用之前,需要使用嵌入式SQL语句CONNECT建立事务对象与数据库的连接。正常情况下,执行Retriev
34、e()后,数据窗口中原有的数据被丢弃,并被新的数据所取代。如果想改变这种默认操作,可以通过在数据窗口控件的RetrieveStart事件中编写代码来实现,方法很简单,只要在该事件的事件处理程序中放上语句“Return 2”即可。这时,Retrieve()检索出的数据将被增加到数据将被窗口原有数据的后面。 如果数据窗口控件中的数据窗口对象需要检索参数,而Retrieve()函数中又没有提供这些参数,那么执行Retrieve()函数时,系统将显示一个对话框,让用户输入检索参数的取值。 执行Retrieve()函数时,可能触发数据窗口控件的DBError、RetrieveEnd、Retrieve
35、Row和RetrieveStar事件。 (2) InsertRow()函数 InsertRow()函数的调用格式为: dwcontrol.InsertRow ( row ) 其中参数row表示插入行前面一行的行号。若row为0,则在最后—行插入新行。 LnsertRow()函数的功能为在数据窗口控件中的指定行前面插入一行。如果数据窗口中某些列定义了默认值,那么在新插入行显示之前,相应数据项的值首先使用默认值进行初始化。 函数执行成功时返回新插入行的行号,函数执行出错时返回–1;如果任何参数的值都为NULL,则InsertRow()函数返回NULL。 新插入的行的编辑状态为New!
36、为该行输入数据以后,其编辑状态变为NewModify!,这时该行才会包含在改变行总数(由ModifiedCount函数获得)之中。 (3) DeleteRow()函数 DeleteRow()函数的调用格式为: dwcontrol.DeleteRow ( row ) 其中,dwcontrol表示数据窗口控件名;row表示要删除数据行的行号,当该参数的值为0时,删除当前行。 删除了数据窗口中的行之后,数据库中的数据并没有变动,只有在应用程序执行了数据窗口控件的Update()函数之后,数据库中的相应数据才会被删除。 (4) RowsMove()函数 RowsMove()函数的调用格
37、式为: dwcontrol.RowsMove ( startrow, endrow,movebuffer, targetdw, beforerow, targetbuffer ) 其中,参数startrow表示移动行的起始行,endrow为结束行,movebuffer为源缓冲区, targetdw为目标数据窗口控件,beforerow表示数据行移动到另外缓冲区的位置,targetbuffer为目标缓冲区。 RowsMove()函数的功能是将一个数据窗口控件中指定的行移动到另一个数据窗口,或将同一个数据窗口控件中一个缓冲区的指定行移动到另一个缓冲区中。 RowsMove()函数的返回
38、值为Integer类型。函数执行成功时返回1,发生错误时返回–1。如果任何参数的值都为NULL,则RowsMove()函数返回NULL。 使用RowsMove()函数把某些行复制到目的数据窗口控件的主缓冲区中后,这些行的修改状态为NewModified!。此时,如果应用程序使用Update()函数更新目的数据窗口控件对应的表,那么PowerBuilder将对新插入的行生成SQLINSERT语句,并把这些语句发送给数据库管理系统。如果在同一个数据窗口控件的不同缓冲区之间移动行,PowerBuilder能够自动改变这些行的状态。例如,如果把未修改过的行从主缓冲区移动到同一个数据窗口的删除缓冲区,
39、那么这些行将被标记为删除状态。如果又把这些行从删除缓冲区中移动到主缓冲区中,则这些行的状态恢复为原来的NotModified!。需要注意的是,当把一个数据窗口中的某些行移动到另一个数据窗口之后,又把它们移动回原来的数据窗口,那么这些行的状态将变为NewModified!,这是因为它们是在不同的数据窗口中移动。 利用RowsMove()函数可以实现从数据窗口的主缓冲区中移动多行数据到删除缓冲区(这时只有在应用程序执行了数据窗口控件的Update()函数之后,数据库中的相应数据才会被删除),也可以把删除缓冲区中的数据移动到主缓冲区中,这样就在应用程序中实现了恢复(Undo)功能。 (5) Up
40、date()函数 Update()函数的语法为: dwcontrol.Update ( { accept {, resetflag } } ) 其中,各参数意义如下。 ● dwcontrol:数据窗口控件名。 ● accept:可选项,boolean类型,指定数据窗口控件在更新数据库之前是否自动执行AcceptText()的功能,该功能把编辑框中的内容放置到缓冲区中。有效取值为:TRUE,默认值,执行AcceptText()函数的功能(如果数据没有通过有效性验证,那么数据更新过程被取消);FALSE,不执行AcceptText()函数的功能。 ● rese
41、tflag:可选项,boolean类型,指明更新数据库后是否自动复位更新标志。有效取值为: ♦ TRUE,默认值,复位更新标志。 ♦ FALSE,不复位更新标志。 该函数的功能是把数据窗口控件中所有的数据修改(插入、删除、修改等)传送到数据库,从而更新数据库中的数据。Update()函数在更新数据库之前会调用AcceptText()函数把“漂浮”在当前行/列上的编辑框中的内容放入到数据窗口控件的缓冲区中。 Update()函数的返回值为Integer类型。函数执行成功时返回1,发生错误时返回–1。如果任何参数的值都为NULL,则Update()函数返回NULL。 在默认情况下,Upd
42、ate函数在完成更新数据库操作以后自动重置编辑状态标记,但是如果用户需要在完成其他有效性检验以后再重置这些标记,可以将Resetflag置为False,然后,当确定更新时调用ResetUpdate函数,重置数据项的编辑标记。 另外,在ItemChanged事件中调用Update函数时,一定要将accept参数置为FALSE,以避免应用程序陷入死循环或发生堆栈错误。以后还会讲到,用户还应避免在ItemChanged事件中调用AcceptText函数,因为该函数的调用将触发ItemChanged事件。 但是,在ItemChanged事件将Update函数的accept参数置为FALSE时也会产
43、生一个问题,因为此时更新的是数据项中的“旧”值,新值还在可编辑控件中。要解决这个问题,就需要在该事件中适当地调用Setltem函数。 10.2 数据窗口控件的重要属性、事件和函数(5) (6) ResetUpdate()函数 ResetUpdate()函数的语法为: dwcontrol.ResetUpdate () 参数dwcontrol指数据窗口控件名。 该函数用于清除数据窗口控件主缓冲区、过滤缓冲区的更新标志并清空删除缓冲区。 该函数执行成功时返回1,发生错误时返回–1。如果dwcontrol的值为NULL,则ResetUpdate()函数返回NULL。
44、当需要在一个事务中更新多个数据窗口时,应用程序可以在更新每个数据窗口时都不清除更新标志。只有所有的数据窗口更新都成功完成后,才能对每个数据窗口调用ResetUpdate()函数清除更新标志。如果某个数据窗口的更新失败,应用程序可以保留更新状态,提醒用户更正错误,之后重新更新数据窗口。使用数据窗口控件的对象函数GetItemStatus()可以找到哪些行标志为更新状态。如果某行在删除缓冲区中,或该行虽然在主缓冲区或过滤缓冲区,但其具有NewModified!或DataModified!的状态,那么该行的更新标志被设置。清除更新标志之后,主缓冲区或过滤缓冲区中的行具有NotModified!或Ne
45、w!状态,并且删除缓冲区被清空。 例如,当需要更新两个数据窗口对象时,可编写如下代码: int rtncode CONNECT USING SQLCA; dw_1.SetTransObject(SQLCA) dw_2.SetTransObject(SQLCA) rtncode = dw_2.Update(TRUE, FALSE) IF rtncode = 1 THEN rtncode = dw_1.Update(TRUE, FALSE) IF rtncode = 1 THEN dw_1.ResetUpdate() dw_2.ResetUpdate() COMMIT US
46、ING SQLCA; ELSE ROLLBACK USING SQLCA; END IF END IF (7) Reset()函数 Reset()函数的调用方法为: dwcontrol.Reset() 该函数用于清除数据窗口控件中的所有数据。执行该函数和在数据窗口中删除数据不同,它只影响应用程序,对数据库不做任何操作。例如,当在数据窗口中使用DeleteRow函数删除一条数据并更新以后,数据库中的该数据不再存在。而当调用了Reset函数以后,数据库没有发生任何变化。 如果用户使用了按需检索(Retrieve As Needed)选项,调用Reset函数将清除已经检索出 来的
47、数据行,但是由于是按需检索,数据窗口会立即检索出下一批数据。如果想避免这种情况发生,可以在调用该函数之前调用DBCancel函数。例如: dw_1.DBCancel() dw_1.Reset() 2. 用于在数据窗口界面中滚动数据行的函数 数据窗口控件包括6个在主缓冲区中滚动显示数据行的函数,分别是Scroll、ScrollToRow、ScrollNextPage、ScrollPriorPage、ScrollNextRow和ScrollPriorRow()函数。 (1) Scroll和ScrollToRow函数 Scroll函数按参数row指定的行数滚动数据窗口中显示的数据,调用语
48、法为: dwcontrol.ScrolI(number) 当row为正数时,数据向下滚动,当row为负数时,数据向上滚动。如果函数调用成功,将返回在控件中第一行显示的数据行号。 ScrollToRow函数用于将数据滚动到用户指定行号row的数据行。它的语法为: dwcontrol.ScrollToRow(row) 调用该函数以后,指定的数据行变为当前行,但是并不高亮显示该行,用户可使用SelectRow高亮显示当前行。 (2) ScrollNextPage和ScrollPriorPage函数 这两个函数用于在数据窗口控件中整页滚动数据,每一次滚动都将改变当前行,但是不改变当前列,
49、调用方法很简单: dwcontrol.ScrollNextPage() dwcontrol.ScrollPriorPage() 这两个函数返回相同的值,都是显示在控件顶端的数据行号。 (3) ScrollNextRow和ScrollPriorRow函数 这两个函数用于逐行滚动数据,每一次滚动都会改变当前行,但是不改变当前列。调用格式是: dwcontrol.ScrollNextRow() dwcontrol.ScrollPriorRow() 使用数据窗口对象的按钮增强对象,也可以实现这些函数的功能。 3. 用于行列控制和数据项的函数 PowerBuilder的数据窗口控件提
50、供了7个用于行列控制和数据项控制的函数,下面分别介绍。 (1) GetRow()函数 GetRow()函数用于返回数据窗口当前行的行号。语法格式为: dwcontrol.GetRow() 参数dwcontrol为数据窗口控件名。该函数的返回值为Long数据类型。函数执行成功时返回数据窗口控件dwcontrol的当前行;如果没有当前行,函数返回0;发生错误时函数返回–1;如果dwcontrol的值为NULL,则返回NULL。 需要注意的是,数据窗口的当前行并非总显示在数据窗口当前的可视区域中,比如,如果当前插入点位于数据窗口的第10行、第5列,然后用户通过拖曳滚动条把可视区域移动到第5






