返回


1996年 .第50期 .软件与编程


编程技巧


PowerBuilder应用开发系列讲座(7)

利用SetActionCode函数控制DataWindow

华天新技术开发公司 张健姿

DataWindow控件的一些事件有一个动作码操纵这个事件之后的缺省动作。在Pow-erBuilder 4.0中我们可以使用SetAction-Code函数,来设置这个动作码的值以控制在这些事件发生后的处理过程。(在PowerBuilder 5.0中,由于事件可以有返回数值,所以采用返回一个整型数值来取代SetActionCode函数,比如使用return 1取代SetActionCode(1),但基本的使用规则两者是相同的。)DataWindow控件中下列事件使用动作码:

CLICKED

DBERROR

ITEMCHANGED

ITEMERROR

PRINTPAGE

RETRIEVEROW

RETRIEVESTART

UPDATESTART

有效的动作码值和应当的处理过程随事件的不同而不同。

Clicked Event

无论何时,当用户在DataWindow控件上点击时,CLICKED事件被触发。如果点击在一个有效的行上,那么DataWindow将自动把此行作为当前行。如果你不想换行,就可以使用SetActionCode来停止。

0 进行换行和CLICKED事件。(缺省)

1 停止处理CLICKED事件。

例如:下面一段代码只允许用户点击在自己的用户号上。

//Clicked Event

//We'll assume there is an instance variable with the current user's

//User ID:string is_user_id

long ll_row

string ls_user_id

ll_row =GetClickedRow()

//No need to continue if the user didn't click on a valid row

if ll_row<1 then

return

end if

ls_user_id=GetItemString(11_row,"user_id")

//If the user_id is not the current user then disallow row change

if ls-user-id<>is-user-id then

beep(1)

SetActionCode(1)

return

end if

ItemChanged Event

DataWindow ITEMCHANGED事件可以有几种不同的操作:接受前一字段的新值,因有错误而拒绝接受新值,拒绝新值但是继续其它的处理过程。这些值如下:

0 接受新的数据值。(缺省)

1 拒绝新的数据值。(启动ItemEr-ror事件)

2 拒绝新的数据值但是焦点改变。

在ITEMCHANGED事件中使用SetAction-Code函数可以进行多字段的交叉确认。例如,银行系统中为确认Account Status是否可以转为Inactive,就需检验Balance字段是否为零:

//ItemChanged Event

Decimal (2) ld_balance //Customer Account Balance

Long ll_currow // Current Row Number

String ls_column_name //The name of the column that changed

String ls_status //Customer Account Status

ll_currow=this.GetRow()

ls_column_name=this.GetColumnName()

CHOOSE CASE ls_column_name

...

...

CASE "STATUS"

ls_status=this.GetText()

//If STATUS is Inactive

IF ls_status= "I" THEN

ld_balance=this.GetItemDecimal (ll_currow,"BALANCE")

IF ld_balance<>0 THEN

//SET AN ERROR

this.SetActionCode(1)

RETURN

ELSE

//ACCERT THE VALUE

this.SetActionCode(0) /* not required since 0 is default */

RETURN

END IF

END IF

END CHOOSE

在程序中,SetActionCode函数不一定要在最后一行,但是由于其他DataWindow函数可能会重置动作码。为了避免这个问题,一般在SetActionCode后面立即执行Re-turn结束这个程序段。

在ITEMCHANGED事件中使用SetAc-tionCode函数用途是可以给该字段一个新值,而不是用户输入的那样。例如:用户将日期输入为星期日,但是我们希望将其改为在此之后的第一个非 休息日。实现这一功能并不像想象的那样简单:

//ItemChanged Event

date ldt_process //process date

long ll_currow // Current Row Number

string ls_column_name // The name of the column that changed

ll_currow=this.GetRow()

ls_column_name=this.GetColumnName()

CHOOSE CASE ls_column_name

...

...

CASE "process_date"

ldt_process=f_get_next_bus_date(date(this.GetText()))

错误 this.SetText(ldt_process)

this.AcceptText()

...

执行上述代码,系统将进入死循环。因为用AcceptText函数改变日期的同时,也触发ITEMCHANGED事件,只是当前列仍在process-data列上,这样就导致堆栈溢出。因此在ITEMCHANGED事件中不能使用Ac-ceptText函数,应使用我们这里介绍的Se-tActionCode这一函数来完成 这一功能:

CASE "process_date"

ldt_process=f_get_next_bus_date(date(this.GetText()))

正确 this.SetItemText(ll_currow,"process_date",ldt_process)//set value in buffer

this.SetActionCode(2) // reject edit control value

RETURN

在Primary!Buffer中将process_date的值置为ldt_process,SetActionCode(2)摒弃用户在edit控件中输入的值(星期日),并允许改变焦点(没有错误发生)。

ItemError Event

在任何时候,当一个DateWindow列没有通过有效性检验或者这个值在ITEM-CHANGED事件中被拒绝时,ITEMER-ROR事件启动。如同ITEMCHANGED事件一样,它的动作码也可以设置为接受或拒绝这个字段的新输入值。它还可以在拒绝新值时,决定是否取消错误信息框的显示。ITEMERROR事件的动作码可以是:

0 拒绝新的数据值并且显示错误信息;(缺省)

1 拒绝新的数据值而不显示错误信息;

2 接受新的数据值;

3 拒绝新的数据值但是允许改变焦点。

如果我们想要在一特定区域显示一个用户自定义的错误信息来代替Power-Builder本身错误信息框,我们可以使用SetActionCode来取消标准的信息框。例如,在前面例子中,当收支 差额不是0是0时,我们就可以用这一方法显示一个错误信息:

//ItemError Event

Long 11_Currow /* Current Row Number */

String ls_column_name /* The name of the column that changed */

ll_currow=this.GetRow()

ls_column_name=this.GetColumnName

CHOOSE CASE s_column_name

CASE "status"

MessageBox("Error","Account cannot be changed to Inactive"+ "Balance is not zero.")

this.SetActionCode(1)

RETURN

...

END CHOOSE

在ITEMERROR事件中使用SetAc-tionCode,我们就可以有选择地忽略DataWindow对象的一个列中输入的有效性规则。例如,在收支差额中,我们有下面这个有效性规则:

Real(GetText())<=10000

客户收支差额不应超过10,000元,如果我们允许使用公司帐户的客户可以超过10,000,我们可以使用如下方式:

//ItemError Event

CHOOSE CASE ls_column_name

CASE "balance"

// Allow balance over $10,000 on Corportate accounts

IF ld_balance not <=10000 AND ls_type="C"

this.SetActionCode(2)

RETURN

END IF

...

我们也可以像前面ITEMCHANGED事件那样在Prinary!Buffer中拒绝新输入的值并填入新值,只是在这里将动作码置为3。

DBError Event

在执行了dw.Retrieve,dw.Update()函数或嵌入式SQL语句并发生了一个数据库错误(SQLCode等于-1)时,触发DBError事件。许多Power-Builder的开发商都在为这种情况设计了标准的数据库错误信息显示。为了使PowerBuilder不显示缺省的数据库错误信息,我们可以使用SetActioncode。DBError事件的动作码值如下:

0 显示错误信息。(缺省)

1 不显示错误信息。

例如:

//DBError event

MessageBox("数据库错误","错误值"+string(this.DBErrorCode)+&

"错误信息为:"+this.DBErrorMessage(),StopSign!)

//Supress PB generated DB Error Message.

this.Set ActionCode(1)

return

PrintPage

PRINTPAGE事件是在执行dw.Print()函数之后,数据传送给打印机之前触发。当打印一个DataWindow时,你可在打印之前设置动作码来跳过一页。PRINT-PAGE事件的动作码如下:

0 不跳过一页;(缺省)

1 跳过一页。

如您打算打印时跳过一页,你可以在中PRINTPAGE编码如下:

//Printpage event

this.SetActionCode(1)

RetrieveRow

从数据库服务器中每次接受了一行记录均启动REIRIEVEROW事件。在这个事件中,你可以设置一动作码来停止检索。下面是RE-TRIEVEROW事件的有效动作码:

0 继续。(缺省)

1 停止检索。

如果一个DataWindow将命中很多行,并且你希望在检索到一定量后停止。你可以在RETRIEVEROW事件中使用SetActionCode:

//RetrieveRow event

//Instance variable Long il_count

...

IF il_count++> 100 THEN

// Maximum rows retrieved,stip retrieval

this.SetActionCode(1)

RETURN

END IF

当用来给被检索行计数的临时变量il_count的值超过100时,检索将停止。

注意:在RETRIEVEROW事件中存在代码,那么检索每一行都会触发事件,这将降低检索的速度。

RetrieveStart

RETRIEVESTART事件在dw.Retrieve()函数之后,产生SQL传送给服务器之前触发。

在一些特定场合可能需要在开始一个检索之前停止它。在RetrieveStart事件中的动作码:

0 继续。(缺省)

1 不检索。

例如:我们让一个用户输入检索标准的窗口,在RETRIEVESTART中判断返回行数是否太多,以决定停止检索并且让用户缩小检索范围。

//Retrieve Start event

Int li_count /*Expected Retrieve Count */

...

//Get count of Rows to be retrieved

...

IF li_count>1000 THEN

MessageBox("Stop","Please narrow your search",stop!)

This.SetActionCode(1)

RETURN

END IF

...

UpdateStart

这一在执行Update()函数之后,产生的修改SQL语句传送给服务器之前触发。

通过设置这一动作码,你可以阻止修改传送给服务器。UPDATESTART事件的动作码如下:

0 继续。(缺省)

1 不修改。

如果你要阻止执行修改语句,在UP-DATESTART事件中使用下列代码:

//UpdateStart event

...

this.SetActionCode(1)

RETURN

...

综 述

在很多情况下,设置动作码是非常有用的。这里的例子,让你对其中几种情况有一个了解。当你对使用PowerScript编码有了更多的经验后,你会发现SetActionCode是非常有用的。

本版责任编辑 刘晓龙