PowerBuilder被忽略的的技术

bingkuaiaj 2007-04-13 03:36:46
加精
1.1 把Object看作类
Completed: 100 %
类(Class),仅仅在概念的层次上,是不能直接使用的,类只有在具体化(实例化)后才能使用,实例化的类我们称之为对象(Object);
在PB的帮助中常常出现Object这个词,例如介绍菜单时使用的名称是Menu Object 而不是 Menu Class。(我认为严格讲,在帮助中这样叫有不妥之处;Sybase可能会有它自己的说法,这些我们暂且不管),为了能合理解释Powerbuilder的面向对象的继承、多态、封装等特性,现在我们作如下假设:
我们暂且把Powerbuilder中的Object统一称作Class;
本次约定在接下来的几次讨论中都有效,如果我能记得我会每次都强调一下;
1.2 窗口的控件创建和释放
Completed: 100 %
控件是我们在开发中最常用的了,但是放在窗口上的控件何时被创建,何时有被销毁?
创建过程:
在windows中,控件被创建时必须指明用来承载控件的窗口对象,所以可以肯定的是窗口的创建过程肯定在所有准备使用它来承载的控件之前完成创建;
细心的话你会注意到控件的Constructor事件会在窗口的Open之前执行,事情就是这样子的,那是因为窗口Open事件并不是窗口的Constructor事件,窗口在完成自己的创建后,再把Control[]中的对象一一创建,在这时控件的Constructor事件会被触发,在所有的控件成功创建完毕后窗口才会触发Open事件。
用流程图表示:

释放过程:
释放过程正好跟创建顺序相反;
在窗口收到WM_CLOSE消息前会先收到WM_CLOSEQUERY消息,来给开发人员一个阻止WM_CLOSE发生的时机;在Powerbuilder中WM_CLOSE <=> Event Close() ,WM_CLOSEQUERY <=>Event CloseQuery()。
所以在窗口关闭时首先触发自己的CloseQuery事件,在CloseQuery同意后触发Close事件,之后才会把Control[]中的控件一一释放,这时各个控件的destructor事件会被触发。等所有的控件被释放后,再触发窗口的Destructor。完成释放过程。
用流程图表示:


注意:控件创建的先后顺序要看控件怎样存储在Control[]中,Powerbuilder无论是创建过程还是释放过程,都是从下表1开始循环创建的,可以查看源码知道各个控件的下标。一般规律是后放入的控件县创建。

1.3 谨慎使用Post
Completed: 100 %
谈到Post,就会想起来是用来向控件消息队列发送消息,通过Post发送的消息处理时间是不能确定的,这由操作系统是如何调度的,以及当时计算机的运行情况来决定。在PowerScript中Post的语法很灵活,表现形式多种多样。
Post以关键字的形式出现:
发送消息给以Powerbuilder事件形式出现的消息处理函数:this.post event open()
发送消息给以Powerbuilder函数形式出现的消息处理函数:this.Post classname( )(这种方法有别于 this.classname())
以关键字形式出现一般用在有参数的消息处理函数中;
并且使用Post是不能得到函数或事件的返回值的;

Post以函数形式出现
this.postevent("XXXX",{Word},{Long})
XXXXX 是函数名或事件名

Windows是消息驱动的操作系统,所以Windows下的Powerbuilder程序也不例外,Powerbuilder中使用Post()和Send()来完成消息的发送。熟悉SDK编成的可以直接使用Post和Send来发送消息,Send发出的消息会立即被处理,所以这个我们不讨论,但是Post是我们的导论范围.
通常情况下Post发送的消息在被对应的消息处理函数处理的时刻要比直接调用消息处理函数晚一些。这就会存在潜在危险,如果发出消息对应的消息处理函数所在的对象已经被释放,这时将可能会出现运行错误或者消息不被处理的危险;所以在使用了Post之后应该注意目标对象是否存在对象提前被释放的情况。特别需要注意的是在窗口的Close中使用Post,因为发出Post时没有办法知道消息何时会被处理。所以在Close中尽量不要使用Post。
这里顺便提到一点:
在控件的代码中,尤其是按钮的Clicked事件中,写了如下代码将会出现运行错误:
CLose(Parent)
this.text = ""
如果出现下面代码则不会出现运行错误:
CLose(Parent)
MessageBox("","")
如果出现下面代码则不会出现运行错误:
Post CLose(Parent)
MessageBox("","")
这些就是Post应用的一些临届情况。

1.4 避免类重名
Completed: 100 %
这里主要讨论两种情况的重名:
1、不同的PBL重名类
Powerbuilder允许在同一个Target中出现多个Powerbuiler Library (PBL文件),在不同的PBL中间出现相同的类别名称,就算是出现同一种类型的类,Powerbuiler不会作出判断,这样就存在了一个潜在的危险,PBL(或PBD)在Target中出现的先后顺序将会影响在运行时引用的对象;并且产生编译警告。所以这种一定要避免。
2、同一个PBL中出现重名
如果是相同类型的重名出现在同一个PBL中,Powerbuiler会作出提示,询问是否要覆盖。但如果出现同名的类不是同一种类型,Powerbuilder不会作出提示,这样就会带来许多不必要的麻烦。例如:在同一个PBL中出现了ww窗口,同时也出现了ww菜单,在ww窗口引用ww菜单时编译器会提示ww不是一个菜单类型。
综上所述第一种重名情况比较致命,不易被发现。第二种情况也应该坚决避免。好在Sybase在引导开发时,都提倡加前缀,这样就可以避免第二种问题。所以要强调的就是手误。

1.5 隐藏的全局类和局部类
Completed: 100 %
隐藏的全局类
打开Powerbuilder相关资料,很容易看到“Powerbuilder一个面向对象的开发工具”之类的话。绝大多数人写过的第一个程序就是在从window建立一个w_main,然后在Application中调用Open(w_main),这样一个程序就产生了
如果有面向对象编成的思想,那么这个时候应该有个疑问,我建立的w_main是个什么东西啊,类?对象?
众多书籍上会说建立一个window对象,那么这时Open(w_main)没有任何疑问,因为w_main是一个全局对象阿,作为参数传给Open当然没有任何疑问。可以你还可能会看到过一下代码:
w_main w_a,w_b
open(w_a)
open(w_b)
上面的代码不但不会产生编译错误,并且能够执行成功。执行后你会看到两个窗口。
你可能会以为对象也能作类别使用,难道Powerbuilder超越了面向对象?
这时应该怀疑的是w_main也是个类,并且有一个与w_main同名的全局w_main对象。只有这样能解释上面提到的两种代码。带着疑问打开w_main的源码:
global type ww from window
global ww ww
看到这里,应该可以证实我们之前的猜测是正确的,Powerbuilder确实创建了window的子类w_main,并且同时又声明与类(Class)同名的全局变量(全局对象 Object)w_main。除了structure(不是类)之外都所有出现在PBL中的类都具有这样的特性。
隐藏的局部类
更深入的编程尤其是写通用代码时,会需要使用ClassName()来判断对象的类别,然后根据类别做出判断。接下来我们仍然以一个具体的例子来展开讨论。
现在有一个窗口w_main,在窗口上方防置了一个按钮cb_1,通常我们写代码都是象下面一样的写法:
cb_1.Text = "XXXX"
cb_1.Enabled = False
String ls_clsNm
ls_clsNm = cb_1.ClassName()
这时就会发现ls_clsNm是“cb_1”,怎么不是CommandButton?难道ClassName()不是取的类别名?查一下帮助,可以证实ClassName()的功能,就是取类名。所以我们又要有猜测,是不是又有局部的类被 cb_1,由于cb_1可以直接用,所以也应该有一个与cb_1同名的局部对象存在。为了证实我们的想法,让我们打开源码分析:
cb_1 cb_1
type cb_1 from commandbutton within w_main
需要注意:如果控件是动态创建的,则ClassName()得到的将是CommandButton。
拨云见日,知道了这些隐藏的类和对象,至少可以肯定Poswebuilder面向对象的特性,我们在以后的编码中巧妙的使用这些类或对象。
...全文
8241 113 打赏 收藏 转发到动态 举报
写回复
用AI写文章
113 条回复
切换为时间正序
请发表友善的回复…
发表回复
zshusen 2012-10-28
  • 打赏
  • 举报
回复
感谢啊!学习一下啊!!!
YOYOZXR 2012-10-10
  • 打赏
  • 举报
回复
Mark
非了 2012-06-20
  • 打赏
  • 举报
回复
哎 初学看不明白。
chuan1186610507 2012-06-07
  • 打赏
  • 举报
回复
学习啦
jimar 2012-06-04
  • 打赏
  • 举报
回复
PB技术群:18555902
mmwmmw_bj 2008-12-04
  • 打赏
  • 举报
回复
好贴,狂顶
Terry200808 2008-12-02
  • 打赏
  • 举报
回复
hao 怎麼沒有圖?
Terry200808 2008-12-02
  • 打赏
  • 举报
回复
hao
tyllen 2008-11-30
  • 打赏
  • 举报
回复
值得学习。
  • 打赏
  • 举报
回复
双向递归,确实可以学习下,虽然感觉代码没这么精简,效率确实不错。
cyh_0769 2008-11-26
  • 打赏
  • 举报
回复
收藏,值得学习了解一下。
做梦的猫 2008-11-26
  • 打赏
  • 举报
回复
关于菜单动态设置代码分散的问题:
虽然 pb 没有象 ON_UPDATE_COMMAND_UI 这样的对菜单状态的监控事件,但我们应该可以自己建立这样的监控,思路如下:

1. 当用户点击菜单后,事件被传送到窗口的自定义事件 parentwindow.TriggerEvent("ue_xxx")

2. 在自定义事件中做两件事:
2.1 将被点击菜单项的名称赋给实例变量 is_menuItemName = "xxx"
2.2 异步触发“菜单状态监控事件”this.PostEvent("ue_update_command_ui")

3. 在监控事件中对所有菜单的状态进行检查并做处理
choose case Lower(is_menuItemname)
case "m_xxx"
if m_main.m_xxx.checked then
...
else
...
end if

case else
//
end choose

如果愿意的话,我们甚至可以做成直接在菜单脚本中异步触发一个监控事件,而监控事件则调用一通用函数对比菜单中所有菜单项的变化情况,并依次调用事件 ue_update_command_ui(menu am_menuItem, boolean ab_visible, ...各种状态)。这样,基本上就可算是完美地模仿了 C++ 的 ON_UPDATE_COMMAND_UI 事件。
weiyangll 2008-11-25
  • 打赏
  • 举报
回复
顶,进来学习
lijianguang 2008-11-19
  • 打赏
  • 举报
回复
学习
dangerous123 2008-09-03
  • 打赏
  • 举报
回复
mark
ziluolan97 2008-09-02
  • 打赏
  • 举报
回复
学习中...
fogle 2008-09-02
  • 打赏
  • 举报
回复
老贴了
javaxi 2008-08-27
  • 打赏
  • 举报
回复
mask,学习
a123lm 2008-05-16
  • 打赏
  • 举报
回复
谢谢归纳

平时都有遇到过相关的,一直没去总结。
liyi830 2008-05-15
  • 打赏
  • 举报
回复
加载更多回复(92)

397

社区成员

发帖
与我相关
我的任务
社区描述
PowerBuilder 非技术版
社区管理员
  • 非技术版社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧