打印本文 打印本文 关闭窗口 关闭窗口
PowerBuilder应用开发系列讲座(30)
作者:武汉SEO闵涛  文章来源:敏韬网  点击数656  更新时间:2009/4/24 21:43:50  文章录入:mintao  责任编辑:mintao
p align="center">在数据窗口中使用滚动条


  在数据窗口中,我们总不可避免要使用到滚动条。在缺省状态下,当用户点击垂直滚动条时,当前的数据窗口滚动显示一页或一行新内容,可是有时我们希望在用户点击滚动条时,系统有另外的响应。在数据窗口的事件中,全局变量message中wordparm属性指示了是何种滚动类型导致了这个事件的发生。

WordParm的值垂直滚动类型
0行向上滚动
1行向下滚动
2页向上滚动
3页向下滚动
4竖直移动

  通过判断这些滚动类型,我们就可以改变它的缺省动作,工对滚动方式进行控制。例如在某些情况下,我们希望用点击滚动条时,记录能够一行一行的滚动。下列的代码可以tabular、freeform和grid表现形式的数据窗口中,实现这样的功。在数据窗口的OTHER事件中:

integerli_wordparmli_wordparm=Message.WodParmifMessage.
Number=277thenifli_wordparm=1orli_wordparm =3thn//捕捉行向下滚动和页向下滚动的事件,使屏幕向下滚动一条记录,并将数据窗口
//的聚焦向下移动一行dw_1.ScrollToRow(dw_1.GetRow()+1)elseifli_wordpar
m=0orli_wordparm=2then
//捕捉行向下滚动和页向下滚动的事件,使屏幕向下
滚动一条记录,并将数据窗口
//的聚焦向上移动一行dw_1.ScrollToRow(dw_1.GetRow
()-1)elseRETURNendif
//避免缺省的数据窗口的滚屏行为Message.Processed=
TRUEendif  

  在开发过程中,我们可能会大量的使用Master/Detal形式的数据窗口来表现数据。所谓Master/Detail风格就是在一窗口中有两个数据窗口组成主表和细目表,分别显示数据中的两张相关联的表,这一格式可用于展现给定事物的两数据的关系。
  使用Master/Detail形式的一种可能性是使两个数据窗口显示同一套数据,其中Master的数据用于浏览,不能修改,而Detail的数据窗口显示的是与Master窗口的相关的更为详细的信息,是可以修改的。这时您希望用户只能够滚动Master窗口,同时使Detail窗口显示响应的信息,而不希望用户能够使用滚动条来滚动Detail数据窗口,翻看无关的信息。
  下面的代码就是用于避免用户滚动Detail数据窗口,翻看到其它行的? 。
  事件名称:Keypressed
  描述:Keypressed为一个用户自定义事件,在数据窗口控件的Script画笔中定义,它的事件编号为pbm_dwnkey,当用户有按键操作时触发。


Script:
IF(KeyDown(keytab!))OR(KeyDown(keyEnter!))OR
(KeyDown(keyDownArrow!))&
OR(KeyDown(KeyUpArrow!))OR(KeyDown(KeyPageDown!))
OR&
KeyDown(KeyPageUp!))&
THEN
This.SetRedraw(False)
//当用户按下上述键时,系统将不与响应,避免数据窗口
自动进行相应的操作
ENDIF


  在上面的的事件中,我们使用了SetReDraw()函数,这将阻塞用户对数据窗口诸如更新等操作,我们必须在下列事件中取消用户对数据窗口进行正常操作的阻塞。
  事件名称:RowFocusChanged

Script:
This.ScrollToRow(myrow)
//myrow是一个实例变量,它的值是这个数据窗口当前应当显示的记录数
This.SetRedraw(True)
//允许对数据窗口进行操作
事件名称:ItemFocusChanged
Script:
This.SetRedraw(True)
//允许用户在同一条记录内进行水平滚动

  在有些情况下,我们会使Master和Detail两个数据窗口显示相同的内容,我们可以使用ShareData()函数令Detail数据窗口共享Master窗口的数据,如何在使用滚动条滚动其中的一个窗口时,另一个窗口能够同步进行滚动呢?如果您没有对Master数据窗口使用RetrieveasNeeded选项,这一个功能的实现是十分简单的。
  假设Master数据窗口名称为dw_1,对其SCROLLVERTICAL事件编程如下:

integervmax_1,vpos_1,vmax_2,vpos_2
stringr_code
decimalvmax_1_percent
vmax_1=integer(dw_1.describe(datawindow.verticalscrollmaximum)) vpos_1=integer(dw_1.describe(datawindow.verticalscrollposition)) vmax_2=integer(dw_2.describe(datawindow.verticalscrollmaximum)) vmax_1_percent=vpos_1/vmax_1
vpos_2=vmax_1_percent*vmax_2
r_code=dw_2.modify(datawindow.verticalscrollposition=+string(vpos_2)) //检验是否修改成功
ifr_codethen
beep(6)
mle_1.text=dw_1scroll=+r_code+vpos_2= +string(vpos_2)
//在scrollvertical事件中无法使用MessageBox弹出错误信息框
endif
Detail数据窗口名称[qu1]为dw_2,对其SCROLLVERTICAL事件编程如下:
integervmax_1,vpos_1,vmax_2,vpos_2
stringr_code
decimalvmax_2_percent
vmax_2=integer(dw_2.describe(datawindow.verticalscrollmaximum)) vpos_2=integer(dw_2.describe(datawindow.verticalscrollposition)) vmax_1=integer(dw_1.describe(datawindow.verticalscrollmaximum)) vmax_2_percent=vpos_2/vmax_2
vpos_1=vmax_2_percent*vmax_1
r_code=dw_1.modify(datawindow.verticalscrollposition=+string(vpos_1)) //检验是否修改成功
ifr_codethen
beep(6)
mle_1.text=dw_1mod+r_code
endif

  谈到这里,我们又要引入一个新话题,这就是在某些事件中避免使用MessageBox的问题:当用户进行的错误操作时,我们应当在屏幕上弹出一个提示框,警告发生的错误或提示将要发生的事情,以引起用户的注意;有些程序员也喜欢在调试程序时,使用MessageBox函数显示当前的系统状态。可是在PowerBuilder的某些改变控件聚焦的事件中,系统是无法显示信息框的,我们必须使用response类型的窗口来取代信息框:在这些事件中使用POST方式调用一个新事件,在新事件中打开这个response窗口。
  某些窗口控件(包括按钮在内)是由于聚焦的改变而捕获鼠标的,在这些控件的某些事件中应避免使用MessageBox函数的。这些事件包括这样几类:
  1.事件名称:

Modified
GetFocus
LoseFocus
ItemFocusChanged
Activate
Deactivate

  不能使用的原因:由于聚焦的改变而导致循环。
  2.事件名称:

ScrollVertical
ScrollHorizontal
ScrollBar对象

  不能使用的原因:MessageBox将导致消息队列的过载,不要在任何卷滚的事件中使用MessageBox函数。
  3.事件名称:

  ReSize

  不能使用的原因:当用户点击MessageBox的OK框后,父窗口将重新获得聚焦,并再次触发resize事件,弹出另外的一个MessageBox,这将导致无穷循环。
  4.事件名称:

  Open(Response窗口)

  不能使用的原因:这将在打开窗口时同时有多个窗口模板,从而导致了不可预料的结果。
  此外,MessageBox还将触发Activate或Deactivate事件。因此有些情况下,您可以将信息写在窗口的标题、微帮助上,或是使用单行编辑器,使用Beep()函数有时也可以达到指示作用,而不必须非使用MessageBox不可。
  我们言归正传,当Master数据窗口没有使用RetrieveasNeeded选项时,上面的代码就可以得到满意的结果,而如果您为了得到更快的响应速度而使用了Retrieveas Needed时,结果就没有这么简单了。在用户点击dw_2的滚动条使之滚动到最下部时,因数据窗口已将数据显示到了最后一条,这就触发dw_1从后台数据库中攫取新的数据,这样当dw_1数据窗口中有了新数据,系统会自动发出消息,使共享数据的dw_2复位,滚回到最初的位置。这样将触发了dw_2的scrollvertical事件,使dw_2和dw_1均滚回到初始的位置,因而无法得到正确的结果。如何解决这个问题呢?有兴趣的读者可以简单思考一下,我们将在下期对这一问题进行进一步的讨论。

打印本文 打印本文 关闭窗口 关闭窗口