荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: Peter (小飞侠), 信区: Program
标  题: 使用PowerBuilder另外500个函数(上)
发信站: BBS 荔园晨风站 (Wed Jan 27 17:44:43 1999), 转信


  乍一看到这个题目,我们可能会觉得很玄。PowerBuilder系统自身
提供的函数大约只有200多个(不考虑多态函数),我们何从得到另外50
0多个函数呢?
    我们在以前讨论过如何使用Windows API标准调用外部函数的问
题。而使用过WindowsS DK编程的开发人员都知道,在USER.EXE、GDI.
EXE等可执行文件和动态连接库中,Windows本身提供了大量目库函数,
这些函数在PowerBuilder中都是可以直接调用的。这样我们的函数库
就一下子又扩充了500多个。
    在这些API函数中,相当一部分是非常有用的,我们将分类向大家
介绍。本期介绍一些在处理自动卷滚条时用到的函数。

    自动卷滚条
    缺省情况下,MDI表单是可以重新设定大小的。这样用户就可以将
窗口设成比原先的小。这种情况下,必须对窗口设置卷滚条的属性,以
访问窗口上的一些控件。而另一方面,除非窗口确实小到不足以显示
所有的控件,否则没有必要提供卷滚条。
    许多Windows的MDI应用在处理这一问题时是这样做的:当窗口小
到无法显示所有控件时,打开卷滚条;而窗口大小合适时,关闭卷滚条
。PowerBuilder系统本身并没有提供自动处理上述操作的功能,但是
我们自己加上这一功能是很容易的,而且实现上述自动卷滚条的功能
也用不到Windows API调用,只需在MDI表单窗口的resize事件中触发
另一个事件,以判断在当前窗口尺寸小于某一阈值时显示卷滚条(后面
将介绍为什么要另外触发一个事件,而不在resiz e事件中直接做)。
此后用户在滚动卷滚条时,窗口会自动随之滚动;当用户再次改变窗口
大小并大于该阈值时,我们应该关闭卷滚条,我们仍然可以不调用Wind
ows API而做到这一点。然而在整个例子中,真正有难度的是在关闭卷
滚条之前,我们需要检查用户是否滚动了卷滚条。如果用户滚动了卷
滚条,我们则应当首先将窗口移回原始状态,这就要用到Windows API
函数了。因为我们需要确定:卷滚条的滚动范围、滚动块在卷滚条上
的当前位置。为了做到这一点,我们需要使用两个Windows API调用:G
etScrollPos和GetScrollRange。
    为了使用这两个API函数,首先在需要使用它们的窗口中将它们声
明为local external函数。在Local external函数对话框中,加入如
下语句:
    Function int GetScrollPos(uint Handle,int Bar)Library"US
ER.EXE"
    SubRoutine GetScrollRange(uint Handle,int Bar,Ref int Mi
nPos,RefintMaxPos)L ibrary"USER.EXE"同时在该窗口中声明如下实
例变量:
    //判断用户是否要最小化窗口
    Boolean ib_minimized=FALSE
    //判断是否显示卷滚框
    int ii_desired_height=1000
    int ii_desired_width=2000
    其中的两个整形变量ii_desired_height和ii_desired_width是
用来决定什么时候打开或移去卷滚条的阈值。当然,每个窗口中都必
须设置这两个变量。为了使窗口更为通用,我们也可以定义一个窗口
级的函数,该函数在窗口的open事件中能分析窗口的control属性
, 也就是窗口内所有控件的最大值,以决定应将以上两个整形变量设
置为多少。
    布尔型实例变量ib_minimized是用来确定用户是否正要将窗口最
小化。如果是,则我们处理卷滚条时会有些不同,稍后我们将讨论这种
情况。
    在open事件中,加入如下语句:
    this.LinesPerPage=10
    this.ColumnsPerPage=10
    this.UnitsPerLine=this.ii_desired_height*.009
    this.UnitsPerColumn=this.ii_desired_width*.009
    监视resize
    接下来要监视resize事件,根据用户改变窗口大小的不同方式,改
变卷滚条的状态。这里的问题是,在移去或加上卷滚条时会引起另一
个resize事件。因此,在resize事件中直接改变卷滚条的状态会引起
递归调用resize事件,这是我们不希望发生的。
    为了防止递归调用,我们要定义一些用户自定义事件,在这些事件
中处理卷滚条的移去或加入。在用户事件对话框中,输入如下值:
    EventName  EventID
    addhscroll pbm_custom01
    addvscroll pbm_custom02
    removehscroll pbm_custom03
    removevscroll pbm_custom04
    syscommand pbm_syscommand
    加入前4个自定义用户事件的语句如下:
    ADDHSCROLL事件:
    //加入卷滚条
    this.hscrollbar=TRUE
    ADDVSCROLL事件:
    //加入卷滚条
    this.vscrollbar=TRUE
    REMOVEHSCROLL事件:
    uint
        WinHandle
    integer
     ScrollPos,MinPos,MaxPos
    //得到窗口句柄
    WinHandle=Handle(this)
    //得到滚动块在卷滚条上的当前位置
    ScrollPos=GetScrollPos(WinHandle,0)
    //得到卷滚条的滚动范围
    GetScrollRange(WinHandle,0,MinPos,MaxPos)
    //滚动窗口
    IF ScrollPos >MinPos THEN Send(WinHandle,276,5,0)
    ScrollPos = GetScrollPos ( WinHandle, 0 )
    //消除滚动条
    this.hscrollbar=FALSE
    REMOVEVSCROLL事件:
    uint
        WinHandle
    integer
     ScrollPos,MinPos,MaxPos
    WinHandle = Handle ( this )
    ScrollPos = GetScrollPos ( WinHandle, 1 )
    GetScrollRange ( WinHandle, 1, MinPos, MaxPos )
    IF ScrollPos > MinPos THEN
    Send ( WinHandle, 277, 6, 0 )
    this.vscrollbar = FALSE
    我们还需要在resize事件中增加下列代码以决定什么时候调用这
些自定义用户事件。
    RESIZE事件:
    //如用户进行的是最小化窗口的操作则返回
    IF ib_minimized THEN
      Return
    ELSE
    //否则考察是否需要卷滚条
    IF this.width < ii_desired_width AND NOT this.hscrollbar
THEN PostEvent (th is, "AddHScroll" )
     IF this.height < ii_desired_height AND NOT this.vscroll
bar THEN PostEvent(  this, "AddVScroll" )   IF this.width >
ii_desired_width AND this.hscrollbar TH EN PostEvent ( this,
"RemoveHScroll" )   IF this.height > ii_desired_height AND t
his.vscrollbar THEN PostEvent ( this, "RemoveVScroll" )END I
F
    SYSCOMMAND事件:
    //如用户试图最小化窗口,则立即取消卷滚条
    IF message.wordparm = 61472 THEN
      ib_minimized = TRUE
      this.vscrollbar = FALSE
      this.hscrollbar = FALSE
    ELSE
      ib_minimized = FALSE
    END IF

    工作原理
    OPEN事件中的代码是为了调整卷滚条的滚动速度。AddHScroll和
AddVScroll中的代码分别加入水平和垂直卷滚条。RemoveHScroll和R
emoveVScroll除分别移去水平和垂直卷滚条外,还要使用WindowsAPI
调用。
    GetScrollPos函数可返回滚动块在卷滚条上的当前位置。我们必
须告诉该函数需要的是哪个窗口上的哪个卷滚条的信息。在WindowsA
PI中,"指向"一个窗口的方法是通过引用它的"句柄"。PowerBuilder
提供了获得应用中的指定窗口句柄的函数,这个函数叫作Handle()。
因为这些自定义用户事件是在窗口自身当中定义的,所以我们只需要
将"this"作为参数传递给Handle函数。0做为第二个参数,告诉Handle
函数我们需要知道水平卷滚条的值;而传递1则表示需要知道垂直卷滚
条的值。
    通过将当前卷滚位置与最小位置相比较,我们就会知道用户是否
滚动过窗口。如果滚动过窗口,我们就向窗口发送一个消息告诉它将
窗口恢复原状。与WM_VSCROLL和WM_HSCROLL消息相对应的消息号分别
是227和226。在WM_VSCROLL中,我们发送SB_TOP(6),它使窗口滚动到
顶部。在WM_HSCROLL中,我们发送5使窗口滚动到左边。
    当用户试图最小化或最大化窗口时,卷滚条的行为会有所不同。
我们知道,PowerBuilde r的resize事件所映射的Windows事件WM_SIZE
是在一个窗口被改变大小以后触发的。而当用户试图最小化一个窗口
时,要在最小化发生之前关闭卷滚条。因此,在这种情况下resize事件
中的代码是来不及起作用的。在这里,我们采取的方法是定义了一个
映射到WM_COMMAND消息的事件。当用户试图最小化窗口时,随该消息
一起发送的值是61472。因此,如果该事件的值是61472,我们只需简单
地移去卷滚条。问题是完成这些操作后,系统还将激发一个resize事
件,resize事件中是引入实例变量ib_minimized的地方。在syscomman
d事件中我们设定实例变量,在resize事件中,检查该变量。该变量告
诉resize事件用户正在最小化窗口,于是resi ze事件就不会处理卷滚
条。如果用户将窗口复原,syscommand事件将再次被激发,但这次传递
给消息的值就不是61472了。因此syscommand事件中仅仅将实例变量
标识复位,于是resize事件就又能处理卷滚条了。

--
※ 来源:.BBS 荔园晨风站 bbs.szu.edu.cn.[FROM: 192.168.1.3]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店