
1996年
.第50期
.软件与编程
编程技巧
PowerBuilder应用开发系列讲座(7)
利用SetActionCode函数控制DataWindow
华天新技术开发公司 张健姿
DataWindow控件的一些事件有一个动作码操纵这个事件之后的缺省动作。在Pow-erBuilder 4.0中我们可以使用SetAction-Code函数,来设置这个动作码的值以控制在这些事件发生后的处理过程。(在PowerBuilder 5.0中,由于事件可以有返回数值,所以采用返回一个整型数值来取代SetActionCode函数,比如使用return 1取代SetActionCode(1),但基本的使用规则两者是相同的。)DataWindow控件中下列事件使用动作码:CLICKEDDBERRORITEMCHANGEDITEMERRORPRINTPAGERETRIEVEROWRETRIEVESTARTUPDATESTART有效的动作码值和应当的处理过程随事件的不同而不同。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_idlong ll_rowstring ls_user_idll_row =GetClickedRow()//No need to continue if the user didn't click on a valid rowif ll_row<1 thenreturnend ifls_user_id=GetItemString(11_row,"user_id")//If the user_id is not the current user then disallow row changeif ls-user-id<>is-user-id thenbeep(1)SetActionCode(1)returnend ifItemChanged Event
DataWindow ITEMCHANGED事件可以有几种不同的操作:接受前一字段的新值,因有错误而拒绝接受新值,拒绝新值但是继续其它的处理过程。这些值如下:0 接受新的数据值。(缺省)1 拒绝新的数据值。(启动ItemEr-ror事件)2 拒绝新的数据值但是焦点改变。在ITEMCHANGED事件中使用SetAction-Code函数可以进行多字段的交叉确认。例如,银行系统中为确认Account Status是否可以转为Inactive,就需检验Balance字段是否为零://ItemChanged EventDecimal (2) ld_balance //Customer Account BalanceLong ll_currow // Current Row NumberString ls_column_name //The name of the column that changedString ls_status //Customer Account Statusll_currow=this.GetRow()ls_column_name=this.GetColumnName()CHOOSE CASE ls_column_name......CASE "STATUS"ls_status=this.GetText()//If STATUS is InactiveIF ls_status= "I" THEN ld_balance=this.GetItemDecimal (ll_currow,"BALANCE")IF ld_balance<>0 THEN//SET AN ERRORthis.SetActionCode(1)RETURNELSE//ACCERT THE VALUEthis.SetActionCode(0) /* not required since 0 is default */RETURNEND IFEND IFEND CHOOSE在程序中,SetActionCode函数不一定要在最后一行,但是由于其他DataWindow函数可能会重置动作码。为了避免这个问题,一般在SetActionCode后面立即执行Re-turn结束这个程序段。在ITEMCHANGED事件中使用SetAc-tionCode函数用途是可以给该字段一个新值,而不是用户输入的那样。例如:用户将日期输入为星期日,但是我们希望将其改为在此之后的第一个非
休息日。实现这一功能并不像想象的那样简单://ItemChanged Eventdate ldt_process //process datelong ll_currow // Current Row Numberstring ls_column_name // The name of the column that changedll_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 valueRETURN在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 EventLong 11_Currow /* Current Row Number */String ls_column_name /* The name of the column that changed */ll_currow=this.GetRow()ls_column_name=this.GetColumnNameCHOOSE CASE s_column_nameCASE "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 EventCHOOSE CASE ls_column_nameCASE "balance"// Allow balance over $10,000 on Corportate accountsIF ld_balance not <=10000 AND ls_type="C"this.SetActionCode(2)RETURNEND IF...我们也可以像前面ITEMCHANGED事件那样在Prinary!Buffer中拒绝新输入的值并填入新值,只是在这里将动作码置为3。DBError Event
在执行了dw.Retrieve,dw.Update()函数或嵌入式SQL语句并发生了一个数据库错误(SQLCode等于-1)时,触发DBError事件。许多Power-Builder的开发商都在为这种情况设计了标准的数据库错误信息显示。为了使PowerBuilder不显示缺省的数据库错误信息,我们可以使用SetActioncode。DBError事件的动作码值如下:0 显示错误信息。(缺省)1 不显示错误信息。例如://DBError eventMessageBox("数据库错误","错误值"+string(this.DBErrorCode)+&"错误信息为:"+this.DBErrorMessage(),StopSign!)//Supress PB generated DB Error Message.this.Set ActionCode(1)returnPrintPage
PRINTPAGE事件是在执行dw.Print()函数之后,数据传送给打印机之前触发。当打印一个DataWindow时,你可在打印之前设置动作码来跳过一页。PRINT-PAGE事件的动作码如下:0 不跳过一页;(缺省)1 跳过一页。如您打算打印时跳过一页,你可以在中PRINTPAGE编码如下://Printpage eventthis.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 retrievalthis.SetActionCode(1)RETURNEND IF当用来给被检索行计数的临时变量il_count的值超过100时,检索将停止。注意:在RETRIEVEROW事件中存在代码,那么检索每一行都会触发事件,这将降低检索的速度。RetrieveStartRETRIEVESTART事件在dw.Retrieve()函数之后,产生SQL传送给服务器之前触发。在一些特定场合可能需要在开始一个检索之前停止它。在RetrieveStart事件中的动作码:0 继续。(缺省)1 不检索。例如:我们让一个用户输入检索标准的窗口,在RETRIEVESTART中判断返回行数是否太多,以决定停止检索并且让用户缩小检索范围。//Retrieve Start eventInt li_count /*Expected Retrieve Count */...//Get count of Rows to be retrieved...IF li_count>1000 THENMessageBox("Stop","Please narrow your search",stop!)This.SetActionCode(1)RETURNEND IF...UpdateStart
这一在执行Update()函数之后,产生的修改SQL语句传送给服务器之前触发。通过设置这一动作码,你可以阻止修改传送给服务器。UPDATESTART事件的动作码如下:0 继续。(缺省)1 不修改。如果你要阻止执行修改语句,在UP-DATESTART事件中使用下列代码://UpdateStart event...this.SetActionCode(1)RETURN...综 述
在很多情况下,设置动作码是非常有用的。这里的例子,让你对其中几种情况有一个了解。当你对使用PowerScript编码有了更多的经验后,你会发现SetActionCode是非常有用的。本版责任编辑 刘晓龙