将窗体从属于主窗体

2008-02-23 05:36:45来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

几乎任何正式一点的C Builder程式除了主窗体外都更有从属窗体,有时是对话框,有时是无模式窗口。VCL使得创建和显示从属窗体都易如反掌。但不是任何程式都适于采用无模式窗体,有些程式需要在一个主窗体内显示不同的内容。本文讨论如何将一个从属窗体“寄居”于主窗体中,从属窗体看上去是主窗体的一部分,用户甚至不知道一个从窗体正被显示。图A显示了一个主窗体,其客户区是个从窗体。

理解子/父联系
  这类程式的基本思路是让任何从属窗体都作主窗体的子窗体,这种设计在其他框架(如OWL或MFC)中很常见,但在VCL程式中却不常见。VCL不允许简单地指定一下属性就使一个窗体从属于另一窗体,要做到这一点还得付出点小小的劳动。您得告诉Microsoft Windows从属窗体是主窗体的子对象,在C Builder编程中一般趋于认为窗体是窗口,元件是子对象,实际上从Windows的观点来看,窗体和元件都是窗口。能够将任一窗口
(窗体和元件)指定为另一窗口的子对象,只要您暂时跳出VCL圈子。

更好的“鼠夹”
  将一个窗体附属于一个主窗体的一个好处是您能够象设计任何其他从属窗体相同设计子窗体,就是说您创建一个新的窗体,在其上添加元件并书写这个窗体的代码。这样使得设计您的子窗体变得容易,并将任何操纵子窗体的代码集中在一个地方。

程式设计范例
  先给出一些程式的背景,程式名叫PARENTING,有一个主窗体,主窗体的顶部和底部各有一个工具条(Tool Bar)和状态条(Status bar),除主窗体外,更有两个子窗体,一个叫TTableForm,用栅格显示ANIMAL.DBF数据表,ANIMAL表是C Builder带的数据库样本的一个表。另一个子窗体TChartForm用Tchart显示ANIMAL表。(假如您购买的C Builder是标准版则没有数据库元件)您能够通过点击菜单项或工具按钮来选择显示表单还是图像窗体,在您作出选择时,活动窗体被摧毁而被选窗体被显示,子窗体在主窗体的工具条下方、状态条上方的客户区显示,而且随主窗体大小变动而随时保持充满客户区。

重载CreateParams()
  如前所述,为让主窗体控制从属窗体,需要将主窗体设为从窗体的“父”,这能够通过重载CreateParams()方法来完成。CreateParams()在VCL创建和窗体联系的窗口时调用,CreateParams()的声明如下:
void __fastcall CreateParams(TCreateParams& Params);
CreateParams()的唯一参数是对一个TCreateParams结构体的引用。在VCL中TCreateParams定义如下:


struct TCreateParams
{
char *Caption;
int Style;
int ExStyle;
int X;
int Y;
int Width;
int Height;
HWND WndParent;
void *Param;
tagWNDCLASSA WindowClass;
char WinClassName[64];
};


  此结构包含了Windows创建一个窗口所需的任何信息(假如您曾用API进行Windows编程,您一定能意识到TCreateParams的成员对Windows CREATESTRUCT结构的映射)。在重载CreateParams()时,首先调用基类的CreateParams()方法,然后修改TCreateParams结构的个别成员变量。一个重载过的CreateParams()方法看起来大致如下:


void __fastcall TChartForm::CreateParams(TCreateParams& Params)
{
Tform::CreateParams(Params);
Params.Style=WS_CHILD|WS_CLIPSIBLINGS;
Params.WndParent=MainForm->Handle;
Params.X=0;
Params.Y=0;
Params.Width=MainForm->ClientRect.Right;
Params.Height=MainForm->ClientRect.Bottom;
}


  程式的关键是配置TCreateParams结构体的Style和WndParent成员,Style设WS_CHILD 和WS_CLIPSIBLINGS窗口式样,WS_CHILD指定窗口为另一窗口的子窗口。根据定义,一个子窗口是没有标题棒的,设计时的标题棒在Windows在运行时创建窗体会被去掉。WS_CLIPSIBLINGS确保主窗口的不同子窗口在窗体绘制时不互相干涉。很明显,一个子窗口必须得有一个父对象,通过将父窗口句柄指定给TCreateParams结构体WndParent 成员就指定了父对象,正如前面代码所示,WndParent成员配置为主窗体的Handle属性。鉴于指定父对象属性相对直接明了,我不在这个主题上深入更多。

配置子窗体的属性
  除了CreateParams()方法中的代码外,还得配置一些子窗体的属性,多数属性能够保留缺省值,但AutoScroll属性应设为false,当然,前提是您的窗体要设计为不必卷动的窗体风格。因为子窗口的大小和位置在CreateParams()中设定,所以Position属性可置为poDefault。Caption和BorderIcon属性将被忽略,故而无需指定。确保BorderStyle置为bsSizeable,更有BorderWidth置为0,假如此二属性设成其他值,子窗体和主窗体会不协调。

窗体的其他元件
  很多时候,除了从属窗体外,主窗体还包含别的元件,比如工具条和状态条,此时配置TCreateParams结构体的X、Y、Width和Height成员时得考虑到工具条和状态条,子窗体应和顶部的工具条和底部队状态条协调。因此配置TCreateParams结构体的成员的代码应该是:


Params.X=0;
Params.Y=MainForm->ToolBar->Height 1;
Params.Width=MainForm->ClientRect.Right;
Params.Height=(MainForm->StatusBar->Top-1)-Params.Y;


  注意Y设为工具条底部加1,子窗体宽度置为主窗体客户区宽度,高度根据子窗体和状态条的顶部计算,基本上为界于工具条底部和状态条底部之间的主窗体客户区。这些就是使从属窗体“寄居”于主窗体的任何需要,您可能更有其他想在子窗体中实现的特征,我将把这些特征的讨论留到后面。

配置主窗体
  主窗体也得进行配置以控制其“收留”的子窗体。首先需要将子窗体从自动创建窗体列表中去掉,需要时再创建他们。假如不从列表中去掉,则当您的应用程式启动时他们会自动显示。您还需要一个变量来跟踪当前的活动子窗体,在主窗体的Public区声明如下变量,Tform * ActiveChild; ActiveChild是公有的,因为子窗体要访问这个变量。我马上会演示如何使用这一变量。现在来书写显示子窗体的代码,先看下面程式行,然后我来解释。


void __fastcall TMainForm::Chart1Click(Tobject *Sender)
{
if(ActiveChild)
delete ActiveChild;

TChartForm * form=new TChartForm(this);
ActiveChild=form;

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: 做一个DreamWeaver风格的程式

下一篇: Windows 中断编程