C++ Builder 动态创建控件(教程)
当开发类似解释程序或实现可视化操作功能等一类的应用程序时,都需要动态地创建控件(对象),而且还要为这些控件添加适当的事件处理程序,下面将介绍在C++Builder中如何实现基本的实现框架。
动态创建控件的一般过程:
TButton *btn = new TButton(this);
btn->Caption = "Button1";
btn->Parent = this;
btn->Show();
下面结合一个动态生成菜单的例子来实践如何动态创建控件并处理添加事件处理。
先编写一个函数用向一个已存在的菜单对象中插入菜单项:
void __fastcall TForm1::AddContextMenuItem(TPopupMenu *pMenu,
AnsiString caption, unsigned int tag, TNotifyEvent notifyEvent)
参数:
pMenu: 已存在的TPopupMenu对象指针
caption: 菜单项的标题
tag: 菜单项的tag值,用于标识不同的TMenuItem对象
notifyEvent: 该菜单项的事件处理函数
函数实现:
TMenuItem *mnuItem = new TMenuItem(pMenu); // Create new item
pMenu->Items->Add(mnuItem); // Add it to pMenu
mnuItem->Name = "CM_" + IntToStr(tag);
mnuItem->Caption = caption;
mnuItem->ImageIndex = imgIndex;
mnuItem->Tag = tag;
mnuItem->OnClick = notifyEvent; // Assign it an event handler
然后编写调用AddContextMenuItem(...)的函数CreateContextMenu(),定义如下:
void __fastcall TForm1::CreateContextMenu(void)
{
FTagInc = 0;
FContextMenu = new TPopupMenu(this);
FContextMenu->AutoHotkeys = maManual;
FContextMenu->OnPopup = UpdateContextMenuItem;
AddContextMenuItem(FContextMenu, "菜单项 1", FTagInc++, MenuItemClick);
AddContextMenuItem(FContextMenu, "菜单项 2", FTagInc++, MenuItemClick);
AddContextMenuItem(FContextMenu, "-", FTagInc++, NullNotifyEvent);
AddContextMenuItem(FContextMenu, "菜单项 3", FTagInc++, MenuItemClick);
}
FContextMenu是TForm1的成员变量,UpdateContextMenuItem()是用于在FContextMenu的Popup事件中更新菜单项。
MenuItemClick与NullNotifyEvent都是TForm1中成员函数,是动态创建的控件的事件处理函数,格式为:
void __fastcall TForm1::MenuItemClick(TObject *Sender)
void __fastcall TForm1::NullNotifyEvent(TObject *Sender)
---------------------------------------------------------------------------------------------
代码如下:
.h文件中:
class TMyThread : public TThread
{
public:
__fastcall TMyThread(void);
private:
void __fastcall Execute();
};
.cpp文件中:
__fastcall TMyThread::TMyThread(void): TThread(true)
{
FreeOnTerminate=true;
Resume();
}
void __fastcall TMyThread::Execute()
{
Form1->createview();
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TMyThread *mythread = new TMyThread;
}
void __fastcall TForm1::createview() //createview()是我自己定义的函数
{
//动态生成LISTVIEW列表
TListView *tempview = new TListView(Form1);
tempview->Visible = true;
tempview->Parent = Form1;
}
就是以上代码运行后出现2个问题:
第一:点击Button按钮时没有创建listview控件
第二:关闭应用程序时出现以下错误提示:
应用程序发生异常 未知的软件异常(0x0eedfade),位置为0x77e8bc3f。
1:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TMyThread *mythread = new TMyThread();
mythread->Execute;
}
2:估计是内存未释放!!
TO:caizhen2000_82(猛将兄!!!)
你的方法不行呀,mythread->Execute;根本没有这个方法。
估计是内存未释放?可以说的具体一点吗?
希望大家给出可行的解决方案,在线等!
Form1->createview(); Form1??
你要把ListView 放在那里?
放在form1上呀
__fastcall TMyThread::TMyThread(void): TThread(true)
{
TListView *ListView1 = new TListView(Form1);
ListView1->Parent= Form1
FreeOnTerminate=true;
Resume();
}
放在构造函数中。
TO: chpst(斗转星移)
非常感谢你的帮助,2个问题全部解决,不过又出现了新的问题!
动态生成的listview如何在createview()函数中调用呀
---------------------------------------------------------------------------------------------
关于动态创建控件
1.个button,动态创建后如何控制它的位置?
2.这个控件要放在另一个控件上,比如panel上,怎么写?
3.如果动态创建的button的名字也是动态的,该怎么写?比如先判断是否要创建,如果需要则创建一个button1,再判断,再需要的话则创建button2,这种情况下如何给button命名?
1 楼fjye(老姜)
TButton *a;
a = new TButton(this);
a->Parent = Form1;
a->Top = 10;
a->Left = 10;
a->Width = 30;
a->Height = 10;
a->Caption = "haha";
如果要放到Panel上,指定的Parent指到Panel上就可以了Top
2 楼fjye(老姜)
动态名字的话我个人比较喜欢用控件数组
比如
TButton *button[10];
创建的方法一样的
button[0] = new TButton(this);
你可以定义个全局变量num,代替方括号里面变量的位置Top
3 楼JUNE20(花和尚:我也要学BCB!)
TButton * TempButton = new TButton(this);
TempButton->Parent = Form1;
TempButton->Top = 00;
TempButton->Left = 00;
... Width = 00;
... Height = 00;
... Caption = 00;
TempButton->Show();
Top
4 楼xiaoshi0(Rain)
动态创建的控件数组是不用名字的,如果要在Panel上创建,只要把该控件的Parent属性设置为Panel就可以了Top
5 楼ToIP(朽木)
//..........
buttone1->Update();Top
6 楼wcccc1(小猪义义)
TButton *a;
string=buttonname="button"+i;//I定义成全局的变量。
a = new TButton(this);
a->Parent = Panel;
a->Top = 10;
a->Left = 10;
a->Width = 30;
a->Height = 10;
a->Name= buttonname;
注,不知道这样指名子行不行。如果系统不让的话没办法了Top
7 楼wcccc1(小猪义义)
别忘了下边I+1
------------------------------------------------------------------------------------
在有些情况由于特殊的需求,需要开发自己的VCL组件以满足需求。对于初学者来说有些问题是需要强调一下的。
第一:就是文件及类的命名问题
菜单操作过程:“Component->New Component...”,在“New Component”对话框的“Unit file name”栏中输入你的类名,如你的类名为“TMyClass”,则这里只要填写“MyClass”,注意这里没有加“T”。确认后会打开该文件。
完成对源文件的编辑并保存后,就要向IDE环境中 安装该组件,操作如下:“Component->Install Component...”,选择“Into new package”页,在“Unit file name”中输入要安装的组件源文件路径及文件名,“Package file name”中输入你要生成的新包文件路径及文件名,注意你里的包名应该为类的名字,如“TMyClass.bpk”,这样就会生成.bpk包文件与包源文 件“TMyClass.cpp”,如果把包名写MyClass.bpk,则你的组件的源文件就会被覆盖掉,当然你可以选择存入在不同的路径下,但这样就会 不容易管理和容易产生混淆。
第二:如何给新的组件自定义图标
一般情况下是需要为自己编写的组件选择一个合适的图标,以更形象地表达该组件的功能,这个图标是在设计阶段在RAD环境中的组件栏中显示,一般大小为24x24。
首先,打开C++Builder 自带的Image Editor,选择“File->New...->Component Resource File(.dcr)”,然后选择“Resource->Bitmap”,输入尺寸和颜色数据,确认后就创建了一个位图让你编辑,默认的资源名为“Bitmap1”,应该将这个名字更改,以和你的.bpl文件名一致,如你的组件的.bpl为“TMyComponent.bpl”,则它的名字应为“TMYCOMPONENT”,并且合部大写。双击该结点就可开始编辑你的图标,当然也可以使用PhotoShop之类的软件做好后直接使用“粘贴”命令粘贴,注意最多支持256色。
当图标绘画完成后就可以存盘,这时必须注意其命名的问题,该文件名必须与你的组件类名一致,如你的组件类名为“MyComponent”,则文件名应为“MYCOMPONENT.dcr”,并且全部大写。再次安装你的组件后就可以使用你自定义的图标了。
上一篇: JWPlayer 使用小记