前往Shuct.Net首页

Shudepb PB反编译专家长时间以来,为业内同类软件事实上的唯一选择.细节,彰显专业.态度,决定品质.

关于PowerBuilder的搜索

PowerBuilder之5年经验谈(一之3)——关键字Post - 编程的夜猫 - 博客园 编程的夜猫的博客 ———小猫的成长乐园 博客园 首页 博问 闪存 新随笔 联系 订阅 --> 管理 随笔- 29 文章- 0 评论- 102 PowerBuilder之5年经验谈(一之3)——关键字Post 返回目录 返回 下页 版权声明 本系列文章在博客园发表,除允许在互联网上自由转载外,不得以其它任何方式拷贝、编辑、印刷出版、制作发行及传播,包括不得未在笔者知晓的情况下制作成各种格式的电子文档并传播,更不得在未经笔者本人允许的情况下以任何形式的拷贝用于商业用途。笔者又本系列文章保留有追究其侵权责任的权利。 若需制成电子文档并用于非商业用途方式的传播,请保留以下版权信息,并与笔者联系邮寄副本一份。 作者:张楠 网名:SummerHeart Email:Costware@163.com Blog:http://summerheart.cnblogs.com/ http://blog.csdn.net/summerheart 时间:2008.6.26 Copyright: 2008 1.3.2 Dynamic为何而存在 在PB中Dynamic是个很有意思的关键字,它允许在PowerScript中动态的调用对象事件或函数,不管这个被调用的事件或函数是否存在,编译器都能通过(点保护时能保存)。但如果在运行时被调用的事件或函数不存在,则会报错并取出程序。其实这是PB的一种后期绑定的机制,又叫动态绑定。也就是用了Dynamic的事件或函数直到运行期才知道实际调用的是哪个事件或函数。PB的帮助中给出的例子如下图关系。 当使用以下脚本调用时 w_a mywindow Open(mywindow, "w_a_desc") mywindow.DYNAMIC Set("hello") 程序运行并不会出错,因为它调用的是w_a_desc的set()函数。Mywindow是一个w_a的变量,但它指向了子类w_a_desc的实例。这是一种典型的装箱过程,但是在父类w_a的定义中并没有Set(String)的这个函数,在这里又能被w_a访问调用。这在程序编写的有些时候是很方便的。 通常的父类是不允许调用子类的特定函数的,因为这会破坏了父类定义的接口规则。这种方法的使用也影响了代码的维护,例如一旦改变了子类w_a_desc该函数接口,编译器并不会在第一时间报出错误,而只能到运行时才会出错。无形时即影响了软件质量,又给测试增加了测试难度。 1.3.3 Post与Send 在讲关键字Create时已经绍介过Windows的消息机制(参见关键字Create),Post与Send就用来向窗口和控件发送消息的,这些消息通过消息队列后最终被处理执行。 if isValid(w_2) then send(handle(w_2),274,61488,0) end if #define WM_SYSCOMMAND 0x0112    //274 #define SC_MAXIMIZE 0xF030 //61488 最大化窗口控件 用Post发送的消息处理时间是不确定的,这取决于操作系统调度的,以及当时计算机的运行情况来决定。我们可以用个例子来测试下Post的调试时间,先创建个nvo对象ou_obj,定义2个实例变量, int foo_a =0 // 函数执行状态。当为1时表示函数被执行 int li_t =0 //记录下执行时的时间 并定义三个函数, public function integer of_foo ()   //用于测试的函数 public function integer of_getfoo () //返回函数执行状态 public function integer of_gettime ()//返回当函数被执行时的时间 对象的源如下: forward global type ou_obj from nonvisualobject end type end forward global type ou_obj from nonvisualobject end type global ou_obj ou_obj type variables int foo_a =0 // 当为1时表示函数被执行 int li_t =0 //记录下执行时的时间 end variables forward prototypes public Function integer()function integer of_foo () public Function integer()function integer of_getfoo () public Function integer()function integer of_gettime () end prototypes public Function integer()function integer of_foo (); li_t =cpu() //记录函数被执行时的时间 foo_a =1 //表示函数被执行了 return 1 end function public Function integer()function integer of_getfoo (); //返回foo是执行标记foo_a return foo_a end function public Function integer()function integer of_gettime (); //返回函数开始执行的时间 return li_t end function on ou_obj.create call super::create TriggerEvent( this, "constructor" ) end on on ou_obj.destroy TriggerEvent( this, "destructor" ) call super::destroy end on 然后我们新建个窗口,定义如下的变量: ou_obj lo_obj //对象的实例 int li_t //保存调用对象函数前的时间 并在窗口上放二个按钮cb_1和cb_2,代码分别如下: cb_1事件代码 int li_s ,li_e lo_obj =create ou_obj li_s=cpu() li_t =li_s lo_obj.post of_foo() li_e=cpu() messagebox("","执行时间 :"+String(li_e - li_s)+"~t函数执行: "+string( lo_obj.of_getfoo())) cb_2的事件代码 if isValid(lo_obj) then messagebox("","执行时间 :"+String( lo_obj.of_getTime() -li_t)+"~t函数执行: "+string( lo_obj.of_getfoo())) end if 运行程序后,先点cb_1调用lo_obj.post of_foo(),再点击cb_2如果如下图: 无论测试多少次点cb_1的结果总是如此: 而点cb_2结果各不相同,且相差很大 无论点击cb_1多少次,都是一样的执行时间为0,并且of_foo()是未被执行的状态。而点了cb_1后再点cb_2,此时函数才被执行过。所以用post调用的函数和事件,是不会被立即执行的,而什么时候执行,是无法确定的。 因此在使用post的时候应注意被调用的对象函数有可能在系统执行时已经被销毁,这时候系统就容易出事调用错误。这种情况往往发生在1、窗口close事件里使用了post调用窗口控件的事件;2、对象的destructor事件里使用了post调用对象函数;3、在destroy对象前使用post调用该对象的函数或事件。以上三种情况都是需要避免的。还有一种情况也应该引起注意的,例如有个函数initListbox对DropDownListBox初始化增加选项,而GetCurrentItem用来获取当前的选项值,如果post调用了initListbox,即使之后使用GetCurrentItem取值也会出错误,因为GetCurrentItem取值时iniListBox有可能还没被执行,初始化选项还没被添加进去,取值要么出错误,要么取到的并非是你想要的值,这就程序带来了隐患。所以这也是需要避免的。 另外来看看Post的几种形式: 1、 Obj.Post foo( ) 发送消息给函数 2、 Obj.Post Event eventname() 发送消息给事件 3、 Obj.PostEvent( "XXXX ",{Word},{Long})以函数形式调用XXXX事件或函数 这三种形式都是一样的原理。形式不同而已。 其实post的这种事后执行的特性也有它方便的时候,例如在一个dw的datetime类型字段中,用户录入年月日,你程序必须把用户的录入再加下当前时间做为字段值保存。如果在itemchanged事件里代码如下,则不可能成功,字段中的值总是用户录入的后面加00:00:00。 datetime ld_date if dwo.name = "c_date" then ld_date = datetime(date(data),now()) this.setitem(row,"c_date",ld_date) accepttext() end if 但如果你把setitem()一句写成this.Post setitem(row,"c_date",ld_date)就可以满足要求。(当然这个例子只是一种解决法,在后面讲Datawindow时笔者还是给出另一种更好的解决方法) 返回目录 返回 下页 posted @ 2008-06-26 19:11 编程的夜猫 阅读(...) 评论(...) 编辑 收藏 刷新评论刷新页面返回顶部 博客园首页博问新闻闪存程序员招聘知识库 公告 Copyright ©2014 编程的夜猫