原则:单向调用,即A调用B,而B不调用A。窗体之间相互调用在结构上是愚蠢的。
一种简单的做法:
A.DoSomething;
begin
B.Create;
try
B.Do(Parm);
finally
B.Free;
end;
end;B.Do(var Parm :Type);
begin
B.InitParm(Parm);
if B.ShowModal = mrOK then
begin
B.ProcessParm(Parm);
end;
end;
一种简单的做法:
A.DoSomething;
begin
B.Create;
try
B.Do(Parm);
finally
B.Free;
end;
end;B.Do(var Parm :Type);
begin
B.InitParm(Parm);
if B.ShowModal = mrOK then
begin
B.ProcessParm(Parm);
end;
end;
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementationuses unit2; ////////////////////////写入对B的调用
const mymsg:=wm_user+100;(自定义消息范围 wm_user+100 到 $7fff)发送消息
sendmessage(form1.handle,mymsg,0,0);捕获消息
procedure wmmymsg(var selfmsg:tmessage); message mymsg;procedure wmmymsg(var selfmsg:tmessage);
begin
...
end;
// DataName为数据的名称,Data为返回的数据,用Variant是为了兼容多种类型,你也可以只用String来表示TFormB = class(TForm)
private
...
FOnRequireData: TRequireDataEvent; function RequireData( const DataName: String ): Variant;public
property OnRequireData: TRequireDataEvent read FOnRequireData write FOnRequireData;end;function TFormB.RequireData( const DataName: String ): Variant;
begin
FOnRequireData( Self, DataName, Self );
end;这样,在FormB中,如果需要FormA中的数据,只需调用RequireData方法即可。而FormA在创建FormB后给OnRequireData事件赋值。做成事件的一个好处是,如果由另外一个Form创建和调用TFormB,则它可以提供自己的数据供应方法,这体现一种多态性及它所带来的灵活性。事件和消息是类似的行为,不过事件则要灵活得多,因为消息只允许有两个整型参数(如果要传递其它类型,需要进行转换),而事件则根据你的具体系统的需要而定义。
我比较喜欢用窗体中的变量来达到相同的目的。
在DELPHI6下再测试,上述约束已经不复存在。