在子窗体的Activate事件中为什么无法正常响应close? ( 积分: 100 )

  • 主题发起人 主题发起人 拉飞
  • 开始时间 开始时间

拉飞

Unregistered / Unconfirmed
GUEST, unregistred user!
测试一:
我建立了一个窗体,在Activate事件中加入以下代码:
procedure TForm1.FormActivate(Sender: TObject);
begin
repeat
Application.ProcessMessages ;
until
Re=44;
close;
end;
一个按钮:
procedure TForm1.Button1Click(Sender: TObject);
begin
Re:=44;
end;
这样在单击按钮的时侯就退出程序了。
[red]得到结论:正常。[/red]

测试二:
Form1的Activate事件去掉。
现在我再增加一个按钮让他生成一个新的窗体:
procedure TForm1.Button2Click(Sender: TObject);
begin
Application.CreateForm(TForm2, Form2);
Form2.ShowModal ;
Form2.Free ;
end;
把窗体Form2中添加Activate事件:
procedure TForm2.FormActivate(Sender: TObject);
begin
Re:=0;
repeat
Application.ProcessMessages ;
until
Re=44;
close;
end;
Form2中加一按钮:
procedure TForm2.Button1Click(Sender: TObject);
begin
Re:=44;
end;
运行程序生成另外一个窗体,当单击按钮的时候无法退出窗体Form2,只有击关闭窗体的“X”才能退出Form2。我单步跟踪了一下。发现执行到close的时候一点反应也没有,到End的时侯就不动了。只有“X”时侯才响应Onclose事件,才能执行到Form2.Free。

我又作了测试三
我在From2中窗体click事件中加入
procedure TForm2.FormClick(Sender: TObject);
begin
Re:=0;
repeat
Application.ProcessMessages ;
until
Re=44;
close;
end;
Form2的Activate事件删除。这时候我点击Form2的按钮Button1,这时候能够正常退出、销毁Form2。

我想请问各位大侠高手:为什么子窗体中Activate事件中无法响应close?
望高手不吝赐教。
 
测试一:
我建立了一个窗体,在Activate事件中加入以下代码:
procedure TForm1.FormActivate(Sender: TObject);
begin
repeat
Application.ProcessMessages ;
until
Re=44;
close;
end;
一个按钮:
procedure TForm1.Button1Click(Sender: TObject);
begin
Re:=44;
end;
这样在单击按钮的时侯就退出程序了。
[red]得到结论:正常。[/red]

测试二:
Form1的Activate事件去掉。
现在我再增加一个按钮让他生成一个新的窗体:
procedure TForm1.Button2Click(Sender: TObject);
begin
Application.CreateForm(TForm2, Form2);
Form2.ShowModal ;
Form2.Free ;
end;
把窗体Form2中添加Activate事件:
procedure TForm2.FormActivate(Sender: TObject);
begin
Re:=0;
repeat
Application.ProcessMessages ;
until
Re=44;
close;
end;
Form2中加一按钮:
procedure TForm2.Button1Click(Sender: TObject);
begin
Re:=44;
end;
运行程序生成另外一个窗体,当单击按钮的时候无法退出窗体Form2,只有击关闭窗体的“X”才能退出Form2。我单步跟踪了一下。发现执行到close的时候一点反应也没有,到End的时侯就不动了。只有“X”时侯才响应Onclose事件,才能执行到Form2.Free。

我又作了测试三
我在From2中窗体click事件中加入
procedure TForm2.FormClick(Sender: TObject);
begin
Re:=0;
repeat
Application.ProcessMessages ;
until
Re=44;
close;
end;
Form2的Activate事件删除。这时候我点击Form2的按钮Button1,这时候能够正常退出、销毁Form2。

我想请问各位大侠高手:为什么子窗体中Activate事件中无法响应close?
望高手不吝赐教。
 
自己先顶一下。
如果在测试二中close换成application.Terminate;那么就可以退出整个程序,我只是想退出Form2。
各位大侠帮忙解释一下。
 
以下是vcl close 源码
你可以看看main form 和一般的form 有什么不同
procedure TCustomForm.Close;
var
CloseAction: TCloseAction;
begin
if fsModal in FFormState then
ModalResult := mrCancel
else
if CloseQuery then
begin
if FormStyle = fsMDIChild then
if biMinimize in BorderIcons then
CloseAction := caMinimize else
CloseAction := caNone
else
CloseAction := caHide;
DoClose(CloseAction);
if CloseAction <> caNone then
if Application.MainForm = Self then Application.Terminate
else if CloseAction = caHide then Hide
else if CloseAction = caMinimize then WindowState := wsMinimized
else Release;
end;
end;
 
to ak_2004:
我已经看过了,如果是main form 的直接关闭程序;如果是MDI窗体的话,隐藏起来或者最小化。不知道有何不妥。
如果在Form2中
repeat
Application.ProcessMessages ;
until
Re=44;
close;
放在其他窗体事件中都可以正常退出Form2就是在Activate事件中无法退出。
望ak_2004大侠赐教。
 
procedure TCustomForm.CMShowingChanged(var Message: TMessage);
const
ShowCommands: array[TWindowState] of Integer =
(SW_SHOWNORMAL, SW_SHOWMINNOACTIVE, SW_SHOWMAXIMIZED);
var
X, Y: Integer;
NewActiveWindow: HWnd;
CenterForm: TCustomForm;
begin
if not (csDesigning in ComponentState) and (fsShowing in FFormState) then
raise EInvalidOperation.Create(SVisibleChanged);
如果不是main form 者会执行这段代码
而在Onactive 时FFormState 为fsShowing
所以出现异常
 
所以你如果在onshow事件里close的话
也是一样
 
试试看是否与showmodal有关
 
如果想在active中关闭form2
你可以在form2的onclose事件中写上
action := cafree;
 
to ak_2004:
谢谢大侠的指点,“如果不是main form 者会执行这段代码,而在Onactive 时FFormState 为fsShowing,所以出现异常”,大侠说的很有道理。但是“如果想在active中关闭form2
你可以在form2的onclose事件中写上,action := cafree;”。我已经原来就试过这种方法,行不通的。因为根本就不响应Onclose事件。所以是否用close都是无关的,如果不信的话,你可以把Close注释掉试一下,都是一样的。

to tzldr:
模态和非模态的方式我都试过,都不行。
感谢两位的积极参与,不管问题是否解决,我都会为两位加分的,以示我对你们的感谢。
 
哦,不好意思,
我刚才测试的时候是用的show,不是用的showmodal
用show是可以的
showmodal暂时还不知道
我可以在看看
 
如果子窗口是自己建立,有没有加上parent:=mainform这个句子啊?
 
to rururu:
由Form1为主窗体建立的Form2,它的父窗体就是Form1,因为我只建立了两个窗体。我已经测试了,加入这个语句对这个程序没有影响。谢谢!
to ak_2004:
感谢大侠回答我的问题,我按照你说的测试了一下。出现了如下问题:
1.如果unit1中的程序,Form2.ShowModal改为Form2.Show,当程序运行到close时侯抛出一 个异常,“Cannot changge Visible in onshow or onhide&quot;,我想可能是已经响应了close,但是在隐藏的时候或者最小化的时侯出现了异常,至于为什么,就搞不清楚了。
2.如果除去close,可以正常运行到close,然后执行Form2.Free。但是,当你没有关闭程序的时侯,点击Form1中的按钮创造窗体的时候,基本没有什么反应。
不知道大侠在测试的时候是否遇到这样的问题。我的问题太多了,麻烦你们了,实在不好意思。
 
1.如果unit1中的程序,Form2.ShowModal改为Form2.Show,当程序运行到close时侯抛出一 个异常,“Cannot changge Visible in onshow or onhide&quot;,
//你没有在form2的Onclose事件中加 Action := cafree;

不加这句就会出现如你所说的那个异常

在form1
form2 := Tform2.create(self);
form2.show;
//form2.free//这句就不要了,不然form2就不能正常显示了

我测试过了,用show是没有问题的
用showmodal的话,form2不会关闭
 
我的测试代码你看看
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

uses Unit2;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
Application.CreateForm(TForm2, Form2);
Form2.Show ;
//form2.Free;//这句就不要了 不然form2就不能正常显示了
end;
end.

unit Unit2;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm2 = class(TForm)
Button1: TButton;
procedure FormActivate(Sender: TObject);
procedure FormClose(Sender: TObject
var Action: TCloseAction);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form2: TForm2;

implementation

{$R *.dfm}
var
Re : integer;
procedure TForm2.FormActivate(Sender: TObject);
begin
Re:=0;
repeat
Application.ProcessMessages ;
until
Re=44;
close;

end;

procedure TForm2.FormClose(Sender: TObject
var Action: TCloseAction);
begin
Action := cafree;//不加这句就会有异常
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
Re:=44;
end;
end.
 
to ak_2004:
我按照大侠所说的Form2.Show试了一下,是可行的,在Show中的确响应了close。从VCL—close的源码中好像是,当onclose执行的时侯,如果Aciton:=cafree,那么下面就要调用release。所以我现在把close换成了:form2.release;可以正常执行。如果是Form2.showmodal就不行了。现在还是不是太明白其中的原因,也许是没有把close的源码完全读懂的原因吧。
非常感谢!稍侯会给大侠加分的。
 
后退
顶部