Effective BCB Form Program
——窗体事件驱动链引发程序错误分析
BCB中采用的类库是VCL,其编程框架是事件驱动的,类似于VB。我在开发过程中发现,如果不对BCB的事件驱动链进行分析,写的程序会带有很多的错误,健壮性很成问题,而且调试很麻烦。
我发现程序中的很多错误都来源于C++的指针操作。在程序中用new的方法创建了一个对象,然后delete这个对象之后,如果此时还有其它指针指向这个对象,访问此对象信息的代码必定会引发异常。这在C++中是常识性的问题。但这个问题在BCB这类事件驱动的开发环境中就复杂化了。由于事件模型其实是对Windows消息循环机制的一个封装,而Windows中一个消息可能会引发一连串的其他消息,所以,事件之间也是相互引发的,形成一个事件驱动的链条。
在BCB这类RAD的开发环境中,窗体(Form)是最核心的组件,窗体的事件模型也是程序中最需要分析的。
我在BCB5中设计了几种典型情况,针对BCB提供的事件模型,绘出了BCB中的事件驱动链。由于WM_PAINT消息的反复激发,所以我有意识地屏蔽掉了对这一消息的响应事件OnPaint。我发现大多数错误就发生成窗体的生成与销毁过程中,其主要的原因就是程序员选错了事件,将代码放错了地方。所以,我重点分析了工程中窗体的创建和销毁过程中的事件驱动链。
先对BCB的工程文件(BPR)进行分析:
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
try
{
Application->Initialize();
Application->CreateForm(__classid(TForm1), &Form1);
Application->Run();
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
return 0;
}
WinMain是BCB工程的入口点,Initialize()一句完成程序的初始化工作,CreateForm()一句完成窗体的创建工作(在此引发一系列的事件),Run()一句则进入了消息循环,此时事件主要是用户操作引发的(当然也有定时器等操作系统引发的事件)。
Catch()一句保证应用程序不会引起操作系统的崩溃。但这也是无数的BCB和Delphi程序会引发“XXX内存读写错误”信息的根源所在。正是为了提高BCB程序的健壮性,我才进行了这个实验,其中比较枯燥,不想看记录的人可以直接去看结论部分。
实验记录:
一、由BCB自动创建的Form的事件驱动链
实验一. 工程中只有一个主窗体Form1
当窗体中只有一个主窗体(Form1)时,程序运行事件的发生次序如下:
创建
Form1构造函数àOnCreate() //到此窗体创建完毕,以下进入窗体的显示过程
àOnShow()àOnActivate()àOnCanResize()àOnConstrainedResize()àOnResize()
窗体显示完毕,以下进入消息循环,等待用户输入.
关闭
关闭主窗体Form1时:
OnCloseQuery()àOnClose() //到此退出消息循环
àOnHide()àOnDestory()à~Form1()析构函数
显然,一个窗体要先隐藏,再销毁,最后再调用析构函数
另外:OnShow()à……àOnResize()这一事件链在各种情况中始终不变,下面的记录中我就以……代表这些不变的事件链。
实验二:工程中有两个窗体,Form1为主窗体,Form2为普通窗体
当工程中有两个窗体,Form1为主窗体,Form2为普通窗体,事件链如下:
创建
Form1构造函数à OnCreate() //到此窗体Form1创建完毕,开始创建Form2
à Form2构造函数
//以下进入Form1的显示过程
àOnShow()à……àOnResize()
除非在代码中指定,缺省情况下Form2只处于加载状态,不会显示,Form2中的OnCreate()等事件代码不会运行。
关闭
关闭时,Form2处于隐藏或显示状态均一样:
Form1的OnCloseQuery()àOnClose() //到此退出工程消息循环,以下销毁Form2
àForm2析构函数àForm1的 OnHide()àForm1的OnDestory()à~Form1()析构函数
值得注意的是,这时,Form2的OnDestory()没有被执行,对应地,当它创建时,Form2的OnCreate()也没有执行!
实验三:工程中有两个窗体,Form1为主窗体,Form2继承自Form1
在BCB中,可以很方便地继承某个窗体,这是BCB的一个非常好用的功能。
创建
Form1构造函数à OnCreate() //到此窗体Form1创建完毕,开始创建Form2
àForm2的OnCreate()àForm1的构造函数àForm2的构造函数 //以下进入Form1的显示过程,同单窗体工程一样àOnShow()à……àOnResize()
值得注意的是:Form2的OnCreate()函数居然先于Form2的构造函数运行!
关闭
1.Form2为隐藏状态,
Form1的OnCloseQuery()àOnClose() //到此退出工程消息循环,以下销毁Form2
àForm2析构函数àForm1的析构函数àForm2的OnDestory()àForm1的 OnHide()àForm1的OnDestory()àForm1的析构函数
注意:Form1的析构函数被执行了两次!
2.Form2为显示状态
Form1的OnCloseQuery()àOnClose() //到此退出工程消息循环,以下销毁Form2
àForm2的OnHide()àForm2的析构函数à Form1的析构函数à Form2的OnDestory()àForm1的 OnHide()àForm1的OnDestory()àForm1的析构函数
注意:Form1的析构函数被执行了两次!
两种情况对比,可以发现只多了一个Form2的隐藏过程.
分享到:
相关推荐
BCB 阻止打开重复窗体
超星格式的。
DLL中的窗体和主程序进行交互显示信息
BCB 编写 如何控制 BCB 窗口 控件 透明部分 希望对大家有所帮助 C++BUILDER 编辑通过
c++ builder 6.0一个简单的窗体设计实例 可供初学者参考
BCB 窗体与控件 组件应用基础 常用事件 事件驱动编程(Event -Driven Programming)就是指通过对事件做出反应来进行编程 常用控件:单选钮和检查框 群组框和单选按钮组 列表框和组合框 等控件的属性方法及实例
bcb6做的特效窗体及图片切换示例 基于SmartEffects控件
BCB源代码:系统与窗体
c++ builder6 自定义形状窗体 图像图片窗体
C++Builder MDI 程序调用 DLL窗体实例。基于 BCB2010
创建不规则窗体 // 设置窗口大小为图片大小 this->Width = Image1->Width; this->Height = Image1->Height; POINT *a; if((a=(POINT*)malloc(800*4*(sizeof(POINT))))==NULL) { ShowMessage("分配内存失败...
参予过较大型项目的朋友应该有这样的体会:一个项目动辄上千个文件,各种窗体多达成百上千个,刚开始接触时常常得费老大的劲才能弄清某些窗体间的继承关系。为了更快地理清窗体之间的关系,我编了这个小东东。 为...
提取Delphi(BCB)编译的exe中窗体的例子
There are pointer to the digital image and prune BCB program.
bcb串口mscomm控件错误编译运行错误修复工具集合c++builder
There are two BCB program.One is Otsu + thinning the other is Otsu + sobel.
常见的情况是辅线程完成某事件后需要“通知”主界面,比如常见的进度条——线程中完成一定的进度后即通知主界面显示到一定的刻度。本程序解决了bcb中回调函数的实用问题,可以当模板套用。代码有一定的注释,简单...
There are five BCB program include dialation, erosion,highboost,RGB image convert to YCbCr and lowpass LoG.
It is a BCB program for digital image by thinning method.
源代码……包含sql查询、更新、插入 删除等功能。 愿与大家分享!!