bitfan(数字世界一凡人)的专栏

在新浪博客的新家:http://blog.sina.com.cn/bitfan

用户操作
[即时聊天] [发私信] [加为好友]
bitfan(数字世界一凡人)ID:bitfan
377064次访问,排名142好友0人,关注者67
=========
几本小书:
《网站建设教程》:高等教育出版社(2005)
《编程的奥秘——.NET软件技术学习与实践》:电子工业出版社(2006)
《.NET 2.0面向对象编程揭秘》:电子工业出版社(2007)。
《ASP.NET程序设计教程》高等教育出版社(2009)。

几堂小课:
在ITCAST(http://www.itcast.net)讲授.NET系列在线视频课程,想将课堂开到互联网上,目标不大,要帮助更多的年轻人学好技术找到好工作。野心不小,已录制了5个系列30节课,打算一路跟踪微软最新技术,打造国内自成体系、独特风格的微软技术系列课程。
bitfan的文章
原创 88 篇
翻译 0 篇
转载 0 篇
评论 2216 篇
最近评论
holon:不错,支持一下。

------------------------------
www.arraylist.cn cn域名免费送
IT人的酒吧式交流平台
-----------------------------
jxgzcxf:有金老师在前面带路,我们学习起这些技术来也相对轻松了些,不至于太迷惘。敬重金老师!
vxbb_free:楼上的说的吓人了
vxbb_free:楼上的说的吓人了
wjfmail:可以学,但估计要比别人多很多的努力.毕竟开发不是一种天赋就可以拥有的才能.你碰的钉子会比别人多得多.不过,还是从现在开始努力吧.
文章分类
收藏
    相册
    .NET技术学习与实践
    5.2 使用.NET开发数据库应用程序
    数据绑定原理
    杂类
    存档
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 Effective BCB Form Program(2) ——窗体事件驱动链引发程序错误分析收藏

    新一篇: 灵活运用面向对象的思想在BCB5中进行高效编程 | 旧一篇: Effective BCB Form Program(1) ——窗体事件驱动链引发程序错误分析

    二、由程序员用new的方法创建的窗体事件驱动链

    在程序中无数次地见到过以下代码:

    TfrmConstant *pForm=new TfrmConstant(this); //创建一个窗体

            pForm->Show();

            ……

            delete pForm;

    我们经常需要动态创建一个Form,再显示它,然后在合适的地方销毁它。

    请注意上面代码中的this参数,它被传送给TfrmConstant窗体的构造函数,这一构造函数有一个唯一的形参——Owner。这个参数决定了由谁负责销毁它。

    BCB的帮助文件中对Owner参数的描述如下:

    Owner描述了谁负责销毁这个组件。

    使用Owner参数来存取component所有者的接口。当一个组件拥有另一个组件时,当父组件内存被释放时,子组件所占的内存资源也被释放。这就是说,当一个窗体被销毁时,窗体上的所有组件也会被删除。

    缺省情况下,一个窗体拥有放在其上的所有组件,同样地,Application对象则拥有所有的Form对象。这样,当程序结束时,Application对象会释放所有Form占用的资源。

    下面是我对Owner参数的实验记录

    实验一:主窗体(Form1new一个普通窗体(Form2)Owner=this

    Form1中的代码示例:

    p2=new TForm2(this);

            p2->Show();

    创建:

    先创建完主窗体后,只调用普通窗体Form2的构造函数,不管显不显示,事件驱动链与以前的实验一样。

    关闭:

    主窗体:OnCloseQueryàOnCloseàOnHide()àOnDestory()à主窗体析构函数àForm2析构函数

    关闭次序是先主窗体再普通窗体,如果创建了多个普通窗体,根据创建的先后顺序按后创建先销毁的原则逐个销毁窗体:

     

    普通窗体是显示还是隐藏对事件驱动链无影响

    实验二:主窗体(Form1) new一个普通窗体Form2Owner=Application

    创建:

    同实验一

    关闭:

    首先是Form1OnCloseQuery()àOnClose()àForm2析构函数(如果有多个,按照后进先出的次序调用) àForm1:OnHide()àOnDestory()àForm1析构函数.

     

    实验三:主窗体(Form1) new一个继承窗体(Form2继承自Form1),Owner=this

    创建:

    创建主窗体Form1,事件链同单窗体的创建;

    接着在代码中开始new Form2:

    Form2 OnCreate()àForm1的构造函数àForm2 的构造函数à创建结束

     

    我们看到要先调用父类的构造函数

    关闭:

    1Form2未显示

    Form1: OnCloseQuery()àOnClose()àOnHid()eàOnDestory()àForm1的析构函数

    àForm2的析构函数à Form1的析构函数à Form2  OnDestory()

    注意:并无Form1OnDestory,同样地:Form1的析构函数被执行了两次

    2Form2显示情况下::

    Form1: OnCloseQuery()àOnClose()àOnHide()àOnDestory()àForm1的析构函数

    Form2 OnHide()à Form2的析构函数à Form1的析构函数à Form2  OnDestory

    仅多了一个Form2 OnHide()过程

    实验四:主窗体new一个继承窗体(Form2继承自Form1),Owner=Application

    创建(Form2不显示情况)

    Form2 OnCreate()àForm1的构造函数à Form2的构造函数

    关闭(Form2不显示情况)

    Form1 OnCloseQuery()àOnClose()àForm2的析构函数à Form1的析构函数à Form2  OnDestory()àMainForm HideàMainForm的析构函数à MainForm  的析构函数

    创建(Form2显示情况)

    Form2 OnCreate()àForm1的构造函数à Form2的构造函数à Form2 OnShow()à ……à Form2:OnResize()

    多了一个显示的事件

    关闭(Form2显示情况)

    Form1: OnCloseQuery()àOnClose()à Form2 :OnHide()àForm2的析构函数à Form1的析构函数à Form2  OnDestory()

    àForm1 OnHide()àForm1 OnDestoryà MainForm1析构函数

     

    三、MDI型应用程序事件发生次序

    主窗体为MainForm,子窗体为MDIChild

    创建

    MainForm构造函数àOnCreate()à……à OnResize()

    新建一个MDI子窗体时,Owner=ApplicationMainForm

    MDIChild 构造函数àOnCreateàshowàActivate

    关闭

    Owner=Application:

    MDIChild OnCloseQuery()(有几个子窗体就执行几次)àMainForm OnCloseQuery()àMainForm OnClose()à MDIChild OnDestory()à MDIChild 析构函数àMainForm OnDestory()àMainForm析构函数

     

    Owner=MainForm:

    MDIChild CloseQuery()(有几个子窗体就执行几次)àMainForm OnCloseQuery()àMainForm OnClose()àMainForm OnDestory()à MainForm析构函数à MDIChild OnDestory()à MDIChild 析构函数

     

    显然,Owner参数决定了主窗体与MDIChild的析构次序。

     

    有用的结论

    从实验中我们可以得出一些有用的结论:

    关于OnCreateOnDestory事件:

    1. FormOnCreate事件是不可靠的,并不像名字所说的当窗体一创建时就执行,而是当窗体是工程的主窗体或是一个继承其它窗体的子窗体时才执行.所以,OnCreate()中初始化变量和创建对象是不合适的;

    2. 在有继承情况下OnCreate事件先于构造函数发生对应地OnDestroy事件后于析构函数发生。

    关于窗体的构造函数和析构函数

    1. 于任何窗体,构造函数和析构函数是可靠的,因为它每一次创建和销毁窗体时都会执行。所以我们应在构造函数中进行程序的初始化操作,在析构函数中清理资源;而不要在OnCreateOnDestory事件中进行处理;

    2. 在继承情况下BCB子窗体对象的构造过程是先构造父窗体,再构造子窗体,这点与C++完全一样,销毁过程则反之;

    3. 在有继承的情况下,父类窗体的构造函数和析构函数则会被执行多次,所以,在这两个地方不要newdelete对象,而应将这类代码放到具体的子窗体类中。如果不这样做,可能会由于多次删除同一对象而引发错误,除非将父类窗体的对象指针声明为static,保证所有子类共享此new的唯一对象!

    4析构函数总是最后调用的,而构造函数总是第一个调用。

     

    关于Owner参数:

    Owner=Application时,先销毁new出来的窗体,再销毁主窗体;

    而当Owner=this(指主窗体)时,先销毁主窗体,再销毁子窗体;

    这个原则对于在窗体内部动态地生成VCL控件时也适用。特别地,当程序中用到了数据模块,或需要动态地生成DataSet等对象时更要注意。因为一个DataSet可能会向多个窗体提供数据(应该避免这样做,合适的方法是new TDataSetOwner参数不设为Application)。

    其它:

    1.  一个Visible=true的窗体一定要先Hide,才能被销毁。

    2. 程序事件链的源头为工程中的主窗体的构造函数

    3. 在有继承情况下,子类窗体实例一定要先Hide才可以被销毁。

    4. 多窗体的管理BCB采用了栈的方法,按创建的次序,先创建的后销毁,千万要避免先创建的窗体含有对后创建的窗体(或其上的控件)的指针。

    5. 关闭时一定会发生OnCloseQuery事件,如果是MDI,此事件还会在MDIChild窗体中传播,所以,在这个地方提示用户改变是合适的。

    6. 有些事件一发生,则定然会跟着一系列的事件,这些事件发生的次序是不变的,比如,只要OnShow事件发生,则一定会接着发生以下事件:

    àOnActivate()àOnCanResize()àOnConstrainedResize()àOnResize()

    OnCloseQuery之后一定是OnClose()

     

     

     

     

     

    发表于 @ 2001年11月05日 23:08:00|评论(loading...)|编辑

    新一篇: 灵活运用面向对象的思想在BCB5中进行高效编程 | 旧一篇: Effective BCB Form Program(1) ——窗体事件驱动链引发程序错误分析

    评论:没有评论。

    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © bitfan(数字世界一凡人)