关于对象状态问题,求解。(100分)

  • 主题发起人 主题发起人 HammerLi
  • 开始时间 开始时间
H

HammerLi

Unregistered / Unconfirmed
GUEST, unregistred user!
有这样一个问题,Form1,Form2两个窗体对象,在Form1中定义Form2类型的窗体级变量,有一个按钮负责创建Form2。想要做到通过判断对象变量是不是nil来判定窗体的状态,当Form2变量是nil时创建窗体,否则不创建,问题在于第一次创建Form2窗体后,变量就不是nil了,如何在Form2窗体关闭时将其设置成nil,以便下次再创建?
 
假如是非模态窗口你要在Form2的FormDestroy里写上Form2:=nil
 
同意yzssg的说法
 
FreeAndNil(Form2);
 
procedure OpenForm(FormClass: TFormClass
var AForm;
AOwner: TComponent = nil);
//根据窗口类名建立窗口,如果窗口存在则只激活它
var
i: integer;
Child: TForm;
begin
for i := 0 to Screen.FormCount - 1 do
if Screen.Forms.ClassType = FormClass then
begin
Child := Screen.Forms;
if Child.WindowState = wsMinimized then
Child.WindowState := wsNormal;
Child.BringToFront;
Child.Setfocus;
TForm(AForm) := Child;
exit;
end;
Child := TForm(FormClass.NewInstance);
TForm(AForm) := Child;
if not assigned(aowner) then aowner := application;
Child.Create(AOwner);
end;
在字窗体的关闭事件中
procedure TForm2.FormClose(Sender: TObject
var Action: TCloseAction);
begin
action:=cafree;
form2:=nil;
end;
 
很多多种方法可以处理。
我一般的做法。
1。子form自定义一个消息,子form在消失前发消息(sendmessage,perform)通知所有者窗体,所有者窗体实现这个消息的处理,把自己的内部变量清理干净。
2。主窗体hook子窗体,截获destroy。可以在before destruction,winproc,ondestroy等很多方法事件里面hook.
3。主窗体在每次使用form2这个变量前,都在整个项目里面查找着各自窗体是否还存在,可以通过子窗体的特殊标记来判断,如标题,tag等。而项目中所有的窗体都自动在screen.forms添加索引。

最后:
如果你肯定只有一个父窗体使用子窗体而且在任何的同一时间只有一个父窗体实例使用子窗体,那么你可以认为form2就代表tform2,把from2声明称成全局变量,直接在tform2的destroy里面把form2清为nil.这样做是最简单了,不过局限也是最大的,但一般情况下都符合这个情况。
 
if not Assigned(Form2) then //Create...
 
各位老大,可能我的问题没有说明白,是这样的:
To yzssg:
Form2 是在 Form1 中的窗体级变量,不是全局变量,所以在 TForm2 的 Destroy 事件里是无法写 Form2 = nil 的。
To xeen:
FreeAndNil(Form2)这句话写在哪里,如果是在TForm2 的 Destroy 事件,那就同上了,在 Form1 的调用过程里?如果我用的是 Show 而不是 ShowModal,那么窗体一创建马上就会消失。
To app2001:
同上
To Laagee:
您说的全局变量方法我没有试通,Destroy事件触发时对象本身还存在,自己把自己设置为Nil好像是不行的。

var
Form2: TForm2
//全局变量



procedure TForm1.Button1Click(Sender: TObject);
begin
if Form2 = nil then
begin
Form2 := TForm2.Create(self);
Form2.Show;
end
else
Application.MessageBox('Form2 isn''t nil!', '错误', MB_ICONERROR or MB_APPLMODAL or MB_TOPMOST);
end;



procedure TForm2.FormDestroy(Sender: TObject);
begin
Form2 := nil;
end;



 
Form2 是在 Form1 中的窗体级变量??
怎么个理解法,定义在哪里???
 
if not Assigned(form2) then
Form2 := TForm2.Create(self);
try
Form2.ShowModal;
//Add you code
finally
FreeAndNil(Form2);
end;
 
To app2001:
不好意思,我的说法有点混淆。Form2是变量名称,也可以是A或者B,类型是 TFomr2,定义在 Form1 的 Private 里。
 
To wuyugen:
这好像是个方法,不过需要修改。首先,这种方法只能够用在 ShowModal,不能用在 Show方法上, 而且前面的 Assigned(form2) 没有必要,因为每次 ShowModal 都必然调用 FreeAndNil() 。如果要用在 Show 上,则要将 try ... finally 更改为 try ... except,并且在 TForm2 的 Close 事件中将 Form2 对象释放(Self.Free OR Self.Destroy),否则下次调用时会直接显示窗体。其次将代码改动成:
procedure TForm1.Button1Click(Sender as TObject);
begin
if not Assigned(form2) then
begin
Form2 := TForm2.Create(self);
Form2.Show;
end
else
begin
try
Form2.ShowModal;
except
Form2 := nil;
Button1Click(Button1);
end;
end;
这样虽然能够实现,但是个人感觉不是很好,求更好的解决方法。
 
后退
顶部