控件内其他窗体调用的问题

jjdelphi 2003-07-14 04:49:59
做一个功能模块,要调用多个窗体,为了使用方便,把调用的多个窗体封装成一个控件。
继承自TComponent。从控件中写方法调用那些窗体。
假如控件为Ttest,有一个属性name,字符串类型。一个方法,ShowName,用于显示。
内部调用的一个窗体frm,放控件Ttest的外部窗体Form1,
frm中怎样调用ShowName方法?还要声明一个Ttest类吗?这个类怎样使用放在Form1上的Ttest的属性?
不知道我是否说明白了?
...全文
22 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
baguli 2003-07-19
  • 打赏
  • 举报
回复
我猜想你的意思,不一定非要用控件实现,用一个API就可以:
function CreateAndShowModalForm(const AOwner: TComponent; const TfrmClass: TCustomFormClass): TModalResult;
begin
with TfrmClass.Create(AOwner) do
try
Name := ClassName + IntToStr(Handle); //保证Form.Name的唯一性
Result := ShowModal;
finally
Free;
end;
end;

其中,TCustomFormClass声明如下:
type
TCustomFormClass = class of TCustomForm;
jjdelphi 2003-07-17
  • 打赏
  • 举报
回复
明白了。
你是放public里面,用到的地方就通过赋值引用?
如果在
constructor test.Create(AOwner: TComponent);
begin
inherited;
frm:=tfrm.Create(Application);//改成frm:=tfrm.Create(Self)
......
就不用你说的了
数字蛋糕 2003-07-17
  • 打赏
  • 举报
回复
其实如果需要更好的封装性的话,可以用reintroduce来创建一个新的构造函数,在函数中添加参数并利用参数来初始化FunctionHolder。这样一来,你的FunctionHolder就不必放在Public中了。

btw. 我的Email:cybercake@silentsea.net
jjdelphi 2003-07-16
  • 打赏
  • 举报
回复
强!如果按你的思路,我下面这个控件怎么改?
控件包有两个文件:est 和 uni。est是包含控件Test类(应该叫est类?)的文件,uni是个内部的窗体文件。est有一个属性S,String类型。一个过程ShowS,用来显示uni窗体。一个函数ErrS,返回'123'和属性S的字符串的连接。
frm是uni.pas的form名字,包含两个edit和一个Button。Edit1显示est的属性S值,Edit2是在Button1Click事件中调用ErrS赋值。比如est1的属性S='abc',那么Edit1.Text='abc',Edit2.Text='123abc'。

est.pas文件
type
Test = class(TComponent)
private
FS:String;
protected
public
function errS:String;
procedure Shows;
constructor Create(AOwner: TComponent);override;
destructor Destroy;override;
published
property S:String read FS write FS;
end;
procedure Register;

implementation

uses uni;

procedure Register;
begin
RegisterComponents('AAA', [TEst]);
end;

{ test }

constructor test.Create(AOwner: TComponent);
begin
inherited;
frm:=tfrm.Create(Application);
end;

destructor test.Destroy;
begin
inherited;
end;

function test.errS;
begin
Result:='123'+fs;
end;

procedure test.Shows;
begin
frm.Edit1.Text:=fs;
frm.ShowModal;
end;

end.

uni.pas文件
type
Tfrm = class(TForm)
Edit1: TEdit;
Button1: TButton;
Edit2: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
frm: Tfrm;

implementation

uses est;

{$R *.DFM}

procedure Tfrm.Button1Click(Sender: TObject);
begin
edit2.text:=test(owner).errs; //这里调用有问题,ErrS的fs与属性S的值不同,还可能有地址访问错误 。
end;

end.
数字蛋糕 2003-07-16
  • 打赏
  • 举报
回复
你可以给所有集成的窗体一个FunctionHolder属性,类型为TTest。
你的TTest实例test1创建这些窗体时,同时将它们的FunctionHolder属性指向自己(Self),即test1,这样一来就行了。但是要注意,声明类的顺序为:

TTest = class;

TMyForm = class(...)
......
public
property FunctionHolder : TTest read ... write ...;
end;

TTest = class(...)
......
procedure ShowName;
end;

procedure TTest.ShowName;
begin
FFunctionHolder.XXXXXXXX;
end;

这只是一种技巧,除非你十分清楚你每一个对象都在做什么,否则容易循环调用导致堆栈溢出。
数字蛋糕 2003-07-16
  • 打赏
  • 举报
回复
漏了一点:

destructor test.Destroy;
begin
frm.Free;//********************************
inherited;
end;
数字蛋糕 2003-07-16
  • 打赏
  • 举报
回复
你的代码里问题多多。

首先你再Test中创建的frm没有释放。

然后你在Form中使用的Owner是Form的Owner,其实也就是Application对象。
所以你的Test(Owner)当然会出错。

应该象下面这样:

unit Est;

interface

type
Test = class(TComponent)
private
FS:String;
protected
public
function errS:String;
procedure Shows;
constructor Create(AOwner: TComponent);override;
destructor Destroy;override;
published
property S:String read FS write FS;
end;
procedure Register;

implementation

uses uni;

procedure Register;
begin
RegisterComponents('AAA', [TEst]);
end;

{ test }

constructor test.Create(AOwner: TComponent);
begin
inherited;
frm:=tfrm.Create(Application);
frm.FunctionHolder := Self;//*************************************
end;

destructor test.Destroy;
begin
inherited;
end;

function test.errS;
begin
Result:='123'+fs;
end;

procedure test.Shows;
begin
frm.Edit1.Text:=fs;
frm.ShowModal;
end;

end.

///////////////////////////////////////////////////////////////////////////////
uni.pas文件
type
Tfrm = class(TForm)
Edit1: TEdit;
Button1: TButton;
Edit2: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
FunctionHolder : TEst;//***********************************
end;

var
frm: Tfrm;

implementation

uses est;

{$R *.DFM}

procedure Tfrm.Button1Click(Sender: TObject);
begin
edit2.text:=FunctionHolder.errs;//************************************
end;

end.
  • 打赏
  • 举报
回复
up
jjdelphi 2003-07-15
  • 打赏
  • 举报
回复
cybercake(数字蛋糕):
比如说我从TTest里面声明一个函数,实现某一个功能。
从frm里面和其他成员里面要调用这个函数的。

为了方便,所以我把他们封装在一起的。
你有好的方法吗?
数字蛋糕 2003-07-14
  • 打赏
  • 举报
回复
frm是不应该调用TTest中的方法的!你的思路有问题。

首先你的frm是TTest的一个成员。你要使用frm中的方法来调用TTest中的ShowName的话,frm必须是已经创建的。然而此时,你只不过需要调用frm中的方法来显示test1的Name属性,何必绕这么大的一个弯子让frm来调用test1中的ShowName,然后又在ShowName中调用frm中的方法呢?
jjdelphi 2003-07-14
  • 打赏
  • 举报
回复
使用的时候,放的控件名字可能命名为test1,frm里面引用的是TTest.ShowName(?), 不是test1。frm里面怎么引用?写Ttest.ShowName是错误的。
李_军 2003-07-14
  • 打赏
  • 举报
回复
你的ShowName是Ttest中的,所以当然要通过Ttest来调用了
gub 2003-07-14
  • 打赏
  • 举报
回复
没听明白,帮你顶吧。
jjdelphi 2003-07-14
  • 打赏
  • 举报
回复
怎么没有人回答?
帮我顶顶也好

5,386

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧