如何动态生成控件?(30分)

  • 主题发起人 主题发起人 thtx5
  • 开始时间 开始时间
T

thtx5

Unregistered / Unconfirmed
GUEST, unregistred user!
如何动态生成控件?怎样释放?
 
Delphi程序中动态生成控件的方法及应用
一、Delphi中生成控件的两种方法
1、 Form(表单)设计中生成控件
在进行Form设计时,直接在控件工具箱选择所需控件,再设置其属性与响应事件,这种方法比较常见。
2、 程序中动态生成控件
有时候,我们需要在程序运行时动态生成控件,这样做有两大优点:一是可以增加程序的灵活性;二是如果生成控件的多少与程序中间运行结果相关,显然方法一是无法的实现的,必须用程序中动态生成方法。
程序中动态生成控件的方法分为三步,首先,定义生成的控件类型,再用Create函数生成控件,最后对控件的相关属性赋值。以TButton控件为例,步骤如下:
(1) 定义控件类型
var
Button1:TButton;
(2) 生成控件
Button1:=TButton. Create(self);
Button1.Parent:=Self;

//一般将其父控件设置为Self,如果不设置Parent的值,
则控件不会在屏幕
//显示出来
(3) 设置其它属性及定义相关事件响应函数,如Caption,Left,Top,Height,Width,Visible,Enabled,Hint和onClick事件响应函数等。
二、动态生成控件方法的应用
在开发生产调度与管理系统中,需要动态生成排产计划图,以甘特图表示,应用Shape控件来显示零件的加工状况(每道工序的加工开始时间与结束时间)是非常适合的。应用Chart控件,对加工设备利用率以三维直方图显示,非常直观。现分别将在程序中动态生成Shape控件和Chart控件的过程加以说明。
1、动态生成Shape控件显示排产计划图(甘特图)
procedure TCreateMultiCharts.ProcCreateCharts;
var
i,j,Rows,Columns,RowSpace,ChartsHeight:Integer;
ShapeChart:array of array of TShape;
begin
Rows:=16;
//Shape控件数组行数
Columns:=8;
// Shape控件数组列数
RowSpace:=20;
// Shape控件行间距
ChartsHeight:=20;
// Shape控件高度
SetLength(ShapeChart,Rows,Columns);
//设置ShapeChart数组大小
for i:=0 to Rowsdo
for j:=0 to Columnsdo
begin
ShapeChart[j]:=TShape.Create(self);
with ShapeChart[i,j]do
begin
Parent:=Self;
//此行必不可少,
否则Shape控件在屏幕显示不出
Shape:=stRectangle;
// Shape控件形状为矩形
Top:=45+i*(RowSpace+ChartsHeight);
Left:=Round(180+Q[i,j].StartTime);
//因Q[i,j].StartTime为实数,故需进行四舍五入取整
Width:=Round(Q[i,j].Value)
Height:=ChartsHeight;

Brush.Color:=RandomColor;
//自定义函数,说明附后
Brush.Style:=bsSolid;
//设置填充方式
Enabled:=True;
end;
end;
end;

注:
(1)Q为一记录型二维数组,定义如下:
type
TempData=Record
Value:Real;
StartTime:Real;
end;
Q:array of array of TempData
并且在另一过程已对Q的分量进行赋值。
(2)为了区分不同的零件,Shape以不同颜色显示,此时,调用了函数RandomColor。该函数为:
function TCreateMultiCharts.RandomColor;
var
red,green,blue:byte;
begin
red:=random(255);
green:=random(255);
blue:=random(255);
result:=red or (green shl 8) or (blue shl 16);
end;

2、动态生成Charts控件的ChartSeries组件,显示设备利用率
procedure TFormMultiMachinesBurthen
.
ShowMachineBurthen
Charts;
var
i:Integer;
Burthen
:Real;
SeriesClass:TChartSeriesClass;
NewSeries:array of TChartSeries;
begin

SetLength(NewSeries,CreateMultiCharts.Rows);
MachinesBurthen
Charts.height:=200;
MachinesBurthen
Charts.Width:=550;
for i:=0 to CreateMultiCharts.Rowsdo
begin
SeriesClass:=TBarSeries;
//设置形状为三维条形图
NewSeries:=SeriesClass.Create(Self);
NewSeries.ParentChart:=MachinesBurthen
Charts;
NewSeries.Clear;
Burthen
:=MachineBurthen
;
Burthen
:=Round(Burthen
*100)/100;
//只取小数点后两位数字
NewSeries.add(Burthen
,'',NewSeries.SeriesColor);
end;
end;

注:
(1) MachineBurthen
为一实型数组,其值为对应设备的利用率,已在另一函数中计算得到;
(2) MachinesBurthen
Charts为TChart控件,在type段说明。
 
可是怎么转换成BC++的代码????
 
转贴:
Borland C++ Builder作为Inprise(原Borland)公司新推出的快速应用程序开发工具(RAD),具有威力强大的C++语言和快捷便利的可视化编程完美结合的优点,遗憾的是其没有直接提供像VB中的控件数组的功能,需要开发者自己编程实现。
   VB中的一个控件数组可以1、允许多个控件共享同一个事件句柄,2、提供了运行期间增加一个控件的机制,3、提供了一种方便的组合控件的方法。前两项在C++ Builder中早已实现,而且CB更有一个优点。即不同类型的控件可以使用相同的句柄(只需在相关控件的Object Inspector窗口中的EVENT事件设置即可)。
   C++ Builder中使用了Tlist类对象来组合控件数组,与VB控件数组元素必须为同一类型控件相比较,C++ Builder中的Tlist类对象可以组合任意类型的控件而不必强求同一种类,这样就大大地方便了程序开发者。例如可以把在不同Panel面板控件上的所有控件组合为一个控件数组。
   作者在开发实时监控程序时,应用Tlist类对象创建、维护了多类型的控件数组。其实现原理与方法详见以下的原程序代码。实例程序实现了动态创建一个包含8个TEdit类型控件和4个TImage类型控件的控件数组,在程序运行中对所创建的控件进行修改、维护的功能(简单起见,只对TImage控件的Parent属性进行了修改,对控件数组中各个控件的属性修改及事件处理句柄均可依此方法修改)。
   1、创建一个新的工程文件(New Application),在Form1上放置两个TPanel类型的Panel1和Panel2,调整大小合适,再在窗体下方放置四个TButton类型Button1,Button2,Button3,Button4,设置控件属性如下:Button1->Caption=“新建控件数组”,Button2->Caption=“改变控件位置”, Button3->Caption=“还原到原位置”, Button4->Caption=“退出”;Button2->Enabled=false,Button3->Enabled=false。
   (注:以下黑体字部分为需要手工添加的代码)
  2、在文件Unit1.H中加入以下声明:
  class TForm1 : public TForm
  {
  __published: // IDE-managed Components
   TPanel *Panel1;
   TPanel *Panel2;
   TButton *Button1;
   TButton *Button2;
   TButton *Button3;
   TButton *Button4;
  private: // User declarations
   TList *MyVCL;
  public: // User declarations
   __fastcall TForm1(TComponent* Owner);
   virtual __fastcall ~TForm1( );
  };
  3、切换到工程的Form界面,双击工程的主界面Form,创建一个OnCreate事件句柄,在文件Unit1.CPP中加入以下代码:
  void __fastcall TForm1::FormCreate(TObject *Sender)
  {
   MyVCL = new TList;//创建TList对象
  }
  将TForm1析构函数加入到文件Unit1.CPP中:
  __fastcall TForm1::~TForm1()
  {
   delete MyVCL;
//删除TList对象
  }
   4、双击标签(Caption)为“创建控件数组”的按钮,创建一个OnClick事件句柄,添加以下代码到OnClick事件句柄中:
  void __fastcall TForm1::Button1Click(TObject *Sender)
  {
   //创建新的控件,调整其位置,并加入到MyVcl(TList 类)之中
   int temptop=5;
   for (int i=0;i<4;i++) {
   TEdit *EditNow = new TEdit(this);
   EditNow->Parent=Panel1;
   EditNow->Text= IntToStr(i);
   EditNow->ReadOnly=true;
   EditNow->Top=temptop;
   EditNow->Height=24;
   EditNow->Width=24;
   EditNow->Left=10;
   MyVCL->Add(EditNow);
//加入到控件数组中
   TImage *ImageOff= new TImage(this);
   ImageOff->Parent=Panel1;
   ImageOff->Picture->LoadFromFile(“None.BMP”);
   ImageOff->Top=temptop;
   ImageOff->Height=24;
   ImageOff->Width=24;
   ImageOff->Left=EditNow->Left+EditNow->Width;
   MyVCL->Add(ImageOff);
//加入到控件数组中
   TEdit *EditStatus = new TEdit(this);
   EditStatus->Parent=Panel1;
   EditStatus->Font->Name = “Arial”;
   EditStatus->Font->Size = 12;
   EditStatus->Text=“禁止访问”;
   EditStatus->ReadOnly=true;
   EditStatus->Top=temptop;
   EditStatus->Height=24;
   EditStatus->Width=80;
   EditStatus->Left= ImageOff->Left+ImageOff->Width;
   MyVCL->Add(EditStatus);
//加入到控件数组中
   temptop=temptop+24+5;
  }
   Button1->Enabled=false;
   Button2->Enabled=true;
  }
  5、同4所示方法,依次双击标签的标题(Caption)为“改变控件位置”、 “还原到原位置”、 “退出”的按钮,创建对应的OnClick事件句柄,添加以下代码到对应的OnClick事件句柄中:
  void __fastcall TForm1::Button2Click(TObject *Sender)
  {
   for (int i=0;i<4;i++)
   ((TImage*)MyVCL->Items[i*3+1])->Parent=Panel2;
   Button2->Enabled=false;
   Button3->Enabled=true;
  }
  void __fastcall TForm1::Button3Click(TObject *Sender)
  {
   for (int i=0;i<4;i++)
   ((TImage*)MyVCL->Items[i*3+1])->Parent=Panel1;
   Button3->Enabled=false;
   Button2->Enabled=true;
  }
  void __fastcall TForm1::Button4Click(TObject *Sender)
  {
   Close();
//关闭窗体
  }
  由上所述,实际的代码大多只是用于设定控件位置和基本属性,真正实现控件数组功能的代码并不太多,也不复杂,而且十分的灵活;需要注意的是使用TList类对象组合中的各项控件之前,必须先将其强制转换为一个对象指针以指明其类型,才能对其属性进行修改/赋值操作。
  本文程序在C++ Builder 3.0/ PWin95,C++ Builder 4.0/ PWin98下调试通过。
 
谢谢两位。
 
后退
顶部