`
wodamazi
  • 浏览: 1470059 次
文章分类
社区版块
存档分类
最新评论

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

 
阅读更多

二、由程序员用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()

分享到:
评论

相关推荐

    BCB程序设计范例——中国象棋

    标题中的“BCB程序设计范例——中国象棋”指的是使用Borland C++ Builder(BCB)这一集成开发环境进行程序设计的一个实例,具体应用是开发一款中国象棋游戏。BCB是一款基于C++的可视化开发工具,它集成了IDE、编译器...

    BCB 阻止打开重复窗体

    在探讨“BCB阻止打开重复窗体”的主题时,我们首先需要理解BCB(Borland C++ Builder)是一款由Borland公司开发的集成开发环境(IDE),主要用于Windows平台上的C++应用程序开发。它提供了丰富的图形用户界面(GUI)设计...

    bcb窗体设计源程序

    2. **窗体(Form)对象**:理解窗体作为应用程序主窗口的角色,以及如何在IDE中创建和编辑窗体。 3. **组件(Component)和控件(Control)**:学习如何从工具箱中选择和添加控件到窗体,如TButton、TLabel、TEdit...

    DLL中的窗体和主程序进行交互显示信息

    窗体(Form)是用户界面的主要组件,包含各种控件和事件处理代码。窗体类应定义为`TForm`的子类,并在DLL的接口部分(`interface`段)声明,以便主程序可以访问。 3. **暴露窗体**:为了让主程序能够显示和操作DLL...

    BCB 图形图像窗体

    在C++ Builder 6(BCB)开发环境中,创建自定义形状窗体和处理图形图像是一项常见的任务,尤其对于设计用户界面(UI)时。BCB 提供了强大的VCL(Visual Component Library)库,使得开发者能够轻松地构建具有丰富...

    BCB 窗体与控件应用基础

    【BCB 窗体与控件应用基础】是C++ Builder 6程序设计中的重要章节,主要涉及事件驱动编程和各种控件的使用。事件驱动编程是一种编程模型,其中程序响应用户或系统的各种事件来执行特定的操作。在这个模型中,程序会...

    提取Delphi(BCB)编译的exe中窗体的例子

    在Delphi和BCB中,窗体(Forms)是用户界面的基础元素,通常保存为*.dfm(Delphi Form)文件。这些文件包含了窗体布局、控件位置、属性设置等所有UI相关的详细信息。在编译过程中,这些*.dfm文件会被嵌入到最终的exe...

    bcb6做的特效窗体及图片切换示例

    【标题】"bcb6做的特效窗体及图片切换示例"主要展示了使用Borland C++ Builder 6(简称bcb6)开发的一种具有视觉特效的窗体应用,其中包括了图片的动态切换功能。Borland C++ Builder 6是一款集成开发环境,特别适合...

    BCB——学生信息查询

    3. **事件驱动编程**:BCB采用事件驱动编程模型,用户界面的每个控件(如按钮、文本框)都可以绑定事件处理器。比如,点击查询按钮时触发一个事件,执行对应的SQL查询语句。 4. **用户界面设计**:BCB提供了一个...

    系统与窗体BCB源代码

    【系统与窗体BCB源代码】是一组基于Borland C++ Builder(BCB)开发的源代码,主要涉及了系统信息获取、任务栏编程、操作系统注册表操作、窗体设计以及状态栏编程等多个核心知识点。这些源代码是学习和理解BCB编程...

    BCB-program7.rar_The Program_bcb_pointer

    BCB的强大之处在于它的可视化设计界面和事件驱动编程模型,使得开发者能够便捷地创建用户界面和编写逻辑代码。 在这个项目中,“pointer”(指针)是一个关键概念。在C++中,指针是一个变量,其值为另一个变量的...

    bcb串口mscomm控件程序编译运行错误修复工具集合c++builder

    标题中的“bcb串口mscomm控件程序编译运行错误修复工具集合c++builder”指的是一款专门针对C++Builder开发环境中的串口通信问题,特别是涉及到MSComm控件时遇到的编译和运行错误的修复工具集。C++Builder是Borland...

    C++BUILDER BCB透明窗体

    在C++Builder(BCB,Borland C++ Builder)中创建透明窗体是一项常见的需求,这主要涉及到Windows API和GDI(Graphics Device Interface)的知识。BCB提供了一个强大的环境来构建图形用户界面(GUI)应用程序,而...

    BCB-program6.rar_There There

    【标题】"BCB-program6.rar_There There" 指的是一个使用 Borland C++ Builder(简称BCB)开发的程序集,其中包含了三个不同的功能模块:鼠标移动、光标移动以及标签显示。这个压缩包文件“BCB program6”可能是包含...

    BCB-program4.rar_OTSU_The Program

    【标题】:“BCB-program4.rar_OTSU_The Program” 涉及的主要知识点是图像处理中的Otsu阈值分割与边缘检测算法的应用,其中BCB(Borland C++ Builder)是一种集成开发环境,用于编写C++程序。 【描述】中提到的两...

    抽奖示例程序 BCB6

    1. **主窗体(Main Form)**:这是程序的核心界面,包含了抽奖按钮、显示结果的文本控件或者列表控件,以及可能的设置选项。 2. **数据管理**:程序可能有一个数据结构用于存储参与抽奖的人员或单位信息,这可能...

    BCB-program9.rar_it

    本压缩包"BCB-program9.rar"包含了一个用BCB编写的特定程序,专注于数字图像处理,特别是运用了细化方法。 细化是图像处理中的一个重要技术,常用于图像分割、特征提取和模式识别等。其主要目的是将图像中的线条或...

    看图猜谜,BCB程序

    【标题】"看图猜谜,BCB程序"揭示了使用Borland C++ Builder(BCB)开发的一个趣味应用程序。BCB是Borland公司推出的一种集成开发环境(IDE),它基于C++语言,提供了丰富的图形用户界面(GUI)组件和事件驱动编程...

    Form Class Scaner (BCB/Delphi窗体类扫描机)

    参予过较大型项目的朋友应该有这样的体会:一个项目动辄上千个文件,各种窗体多达成百上千个,刚开始接触时常常得费老大的劲才能弄清某些窗体间的继承关系。为了更快地理清窗体之间的关系,我编了这个小东东。 为...

    C++ Builder MDI 调用 DLL 子窗体(基于 BCB2010)

    2. 在MDI父窗体项目中加载DLL,获取并调用函数。 3. 在MDI父窗体中管理由DLL创建的子窗体。 4. 可选地,通过接口增强DLL与MDI父窗体间的通信。 这种设计方式使得MDI程序的结构更加清晰,有利于代码的维护和扩展。在...

Global site tag (gtag.js) - Google Analytics