4.3 窗体的更多细节
使用IDE创建一个窗体的同时,C++Builder会自动地通过在WinMain()函数中加入代码来在内存中创建窗体。这也是一般所需的方式,可以不必去改变。也就是说,在整个程序范围内主窗口是一直存在的,所以为主窗口创建窗体时,可以不必改变C++Builder的缺省方式。
不过,你可能不希望在程序运行时,所有应用程序的窗体都驻留在内存中,若不希望应用程序的 对 话框同时留在内存中,可以在需要的时候动态地创建它们 。
窗体可分为模态(Modal)和非模态(Modeless)两类,模态窗体指的是用户在切换到其他窗体之前需与之交互的窗体(例如,对话框就要求用户的输入)。非模态窗体是指一直显示的窗口,直到用户关闭或将其最小化,或者是被其他窗口盖住。
4.3.1 控制窗体何时驻留内存
缺省时C++Builder会通过在应用程序的WinMain()函数中加入下列代码,自动地在内存中创建应用程序主窗体。
这个函数创建了一个与窗体同名的全局变量,应用程序中的每个窗体都对应一个全局变量,这个变量是指向窗体类的实例的指针,并在程序运行的同用于引用窗体,所有包含窗体头文件(.h)的源代码 (.cpp)文件都可以通过这个变量来访问窗体。
因为窗体被加入到WinMain()函数中,所以当程序一激活,窗体就会出现,同时在整个应用程序运行时都驻留在内存中。
1.显示自动生成的窗体
假如选择在程序启动时创建窗体,但想在稍后再显示它,这时可在窗体事件处理程序中用Show Modal方法来显示一个已存在于内存中的窗体。
在这种情况下,由于窗体已存在于内存中,故不用再创建另一个实例或析构那个实例。
2.动态创建窗体
有时不希望应用程序中的所有窗体都驻留在内存中,为减少程序载入时所需的内存数,可以在需要使用某些窗体时才创建它们。例如,对话框就只在用户需和它交互时才需出现在内存中。
为在运行时不同阶段使用IDE创建窗体:
1) 从组件栏中选择FileNewForm菜单项以显示新窗体。
2) 从PRojectOptionsForms页中的自动创建的窗体列表中,将该窗体删除。这也就是从WinMain()函数中删除窗体的调用,也可自行从WinMain()函数中删除下面这一行:
3) 需要调用窗体时,对于非模态窗体可使用Show方法,对于模态窗体可使用ShowModal方法。
主窗体的事件处理程序必须创建结果窗体的实例,并负责删除它,调用结果窗体的方式之一是使用全局变量,如下所示。注重ResultsForm是一个模态窗体,处理程序将使用ShowModal方法。
例中事件处理程序会在窗体关闭之后删除它,因此若需要在应用程序的其他地方使用ResultsForm,就需要使用new重新创建它,若窗体是使用Show方法显示的,则不能在文件处理程序中删除它,因为Show需在窗体是打开时返回。
注重使用new操作符创建窗体时,要确保该窗体不在ProjectOptionsForms页的自动创建窗体的列表中,确切地说,假如创建一个窗体而没有从自动创建窗体列表中删除同名的窗体,则C++Builder会在启动时创建窗体,同时事件处理程序会创建一个新的实例,并会重载对自创建实例的引用,自动创建的实例虽存在,但应用程序无法再访问到它。而当事件处理程序结束时,全局变量不再指向一个有效窗体,所有对该全局变量的调用都可能会造成应用程序崩溃。
3.创建窗口之类的非模态窗体
只要窗体仍在使用,就必须保证非模态窗体的引用变量的存在,也就是说这此变量必须有全局范围,大多数情况下,必须使用窗体创建时生成的全局变量(变量名和窗体的Name属性相同),假如应用程序需要窗体的额外的实例,必须为每个实例声明单独的全局变量。
4.使用局部变量创建窗体实例
创建模态窗体个别实例的较安全方法是在事件处理程序中使用局部变量作为新实例的引用。假如使用局部变量,就可以不必关心ResultsForm是否为自动创建的了,事件处理程序的代码不会引用全局窗体变量。例如:
可以注重在这个事件处理程序中没有使用窗体的全局实例。应用程序一般使用窗体的全局实例。不过,若需要模态窗体的新实例。或是在应用程序的个别的块(例如某一个函数)中使用窗体。使用局部实例则是最安全有效的方式。
当然,非模态窗体的事件处理程序中不能使用局部变量。因为非模态窗体必须具有全局范围以保证在窗体使用过程中一直是存在的窗体一打开。Show就会返回。因此,若使用局部变量,将会立即失去其作用域。