为什么我的Form无法响应FormClose事件呢?(100分)

  • 主题发起人 主题发起人 ow
  • 开始时间 开始时间
O

ow

Unregistered / Unconfirmed
GUEST, unregistred user!
我在一个Form中添加了一个按钮,点击该按钮,就执行如下的语句:
var
InWorking: Boolean;

procedure TMyForm.Create
begin
InWorking := False;
end;

procedure TMyForm.btnStartClick
begin
if InWorking then
begin
InWorking := False;
Exit;
end;

repeat
执行某一工作;
Application.ProcessMessages;
until not InWorking;
end;

其中InWorking是一个标志,而按钮的效果就是启动/停止某一工作。
现在我希望在该工作启动后,用户关闭Form时将自动停止该工作,于是
我在FormClose中加了如下语句,
procedure TMyForm.FormClose
begin
InWorking := False;
end;
但是发现启动工作后,点击关闭Form的按钮无效,也根本不执行FormClose过程,
而用按钮手工停止工作后,再按关闭Form的按钮则会正常执行FormClose过程,请问
这是怎么回事?(执行的工作需要的时间较短,但是需要循环运行,所以使用repeat
循环执行)。
 
我试过了,没有你说的问题。

>根本不执行FormClose过程
看来问题应该在“执行某一工作;”,有可能是它屏蔽了Close消息,我用的是Sleep(Random(1000));,
一切正常。(在repeat之前加了一句 InWorking:=true;)
 
好像没有你说明的问题。
不过兄弟你的东东也太奇怪了。你的程序是一个死循环(循环标志一真为True)
 
我也觉得很奇怪,在执行某工作时其他事件都响应的,就是不响应FormClose事件。
另外很抱歉,刚才发贴子的时候btnStartClick中少了一句InWorking := True;,程序
里是对的。(creation-zy已经指出了,真是高手)

procedure TMyForm.btnStartClick
begin
if InWorking then
begin
InWorking := False;
Exit;
end;

InWorking := True;

repeat
执行某一工作;
Application.ProcessMessages;
until not InWorking;
end;
 
当一个窗体关闭并被释放后会依此产生五个事件:
onclosequery
onclose
ondeactivate
onhide
ondestory
如果关闭一个应用程序的主窗体,该程序其他所有被打开的窗体都会
被隐含地关闭,并且不会激发onclose事件,不过onclosequery事件总
会被激发。
ok?
 
to 张剑波:
我的TMyForm不是主窗体,而且关闭是点击TMyForm自己的关闭按钮,和主窗体无关,所以
可能不是你说的这种情况。另外为什么我在执行循环的时候无法响应FormClose事件,而结束
循环后又可以响应了呢?我在循环中已经加了无数句Application.ProcessMessages, 另外
其它事件,如点击控件,选择表项等都可以在执行循环的时候得到相应。请问这是什么原因?
 
如果是mdi的子窗体,且action不是cafree,就会产生你的现象.
不是cafree,就没有被释放,故不产生onclose事件.
请多指教.
 
我的TMyForm不是mdi的子窗体,它是一个模态对话框, 窗体属性为fsNormal。
我在FormCloseQuery和FormClose里都设置了断点,但是在执行循环的时候试图关闭
窗体时都无法进入这两个过程,而循环跳出后则可以先后进入这两个过程。

我循环中完成的工作是不断的画窗体上的一个TLabel对象,即调用
MyLabel.Canvas.Draw(0, 0, Bitmap);
这会影响FormClose事件的执行吗?
 
to creation-zy:
你只要这样试就会碰到我的问题了:
1.建立一个Application,主窗体为Form1.
2.添加一个窗体Form2,为TForm2加一个私有变量
private
FStop : Boolean;
然后在窗体上添加一个Button1, 并响应其Click事件如下:
procedure TForm2.Button1Click(Sender: TObject);
begin
repeat
Application.PRocessMessages;
until FStop;
end;

最后在窗体的Close事件(CloseQuery事件也可以)中加入如下语句:
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
FStop := True;
end;
或者设置断点也可。

3.在主窗体Form1中显示Form2如下:
with TForm2.Create(Self) do
begin
ShowModal;
Free;
end;

然后启动程序,在Form1中调用Form2,然后按下Form2中的Button1,此后再按Form2的关闭
按钮则无效了。
 
这个问题看来比较复杂,我决定再加100分,请各位高手不吝赐教。
 
在from2上再加一个Button2, 并响应其Click事件如下:
procedure TForm2.Button2Click(Sender: TObject);
begin
fstop:=true;
self.close;
end;
 
to zzh0918:
我考虑过你提出的方法,但是希望能尽量避免用这种方法,因为Windows为窗体提供了
标准的关闭按钮,用户总是希望通过这个按钮可以关闭窗体,当他发现无法关闭时,就觉
得你的程序有问题了(尽管你为他另外设置了一个“关闭”button)。
 
to ow

按你 ID:562755 的帖子做确实有问题,但是在FormCreate事件中加上

FStop:=True; 后就一点问题都没有了,我想是不是因为 FStop没有初始化的问题。
 
哦,搞错了,不好意思
 
添加捕捉消息,方法如下
TForm2 = class(TForm)
....
....
procedure WMClose(var Message: TMessage); message WM_CLOSE;
private
fstop: boolean;
end;
end;

procedure TForm2.WMClose(var Message: TMessage);
begin
FStop:=True;
inherited;
end;
 
to lollman:
你提供的响应WM_CLOSE消息的方法是可行的,可是为什么我原来的程序会有问题呢?是
Delphi 5的Bug吗?
 
别问我,我也不知道,再请教高人吧
 
你在from关闭时应传回一变量,clo:=true

epeat
执行某一工作;
Application.ProcessMessages;
until (not InWorking)or (clo=true);

 
to dana:
请问你的clo变量在哪里设置为True? 能否具体一点?谢谢。
 
改用 Show; 就可以了。用 ShowModal 方法显示窗体的时候对某些信息进行了处理,例如:
Use ShowModal to show a form as a modal form. When the form is shown in a modal state,
the application can't continue to run until the form is closed.
To close a modal form, set its ModalResult property to a nonzero value.

看一看 function TCustomForm.ShowModal: Integer; 的源码,它对消息进行了过滤。

因此,这不应该是Delphi的Bug。如果不愿改变显示方式,还是采用lollman的响应WM_CLOSE消息的方法吧。
(无边界窗体+退出按钮也可以)
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
511
import
I
D
回复
0
查看
1K
DelphiTeacher的专栏
D
I
回复
0
查看
683
import
I
后退
顶部