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

  • 主题发起人 主题发起人 ow
  • 开始时间 开始时间
to creation-zy:
看了你的解释,还有两点不明白,还请指教。
1.如果是ShowModal对消息过滤,为什么不执行repeat until任务时还是可以触发
FormClose事件?
2.关于ModalResult的问题,我试过在Form上加了一个btnCancel,其ModalResult为
mrCancel。但是在执行repeat until时仍然无法通过按btnCancel来触发FormClose
事件?
 
看一看:function TApplication.ProcessMessage(var Msg: TMsg): Boolean;
if Msg.Message <> WM_QUIT then
~~~~~~~~~
begin
...
end
else
FTerminate := True;
~~~~~~~~~~~~~~~~~~~~

ShowModal中:

repeat
Application.HandleMessage;
if Application.FTerminate then ModalResult := mrCancel else
~~~~~~~~~~~~
if ModalResult <> 0 then CloseModal;
until ModalResult <> 0;

只要在ProcessMessage过程中没有得到WM_QUIT消息,FTerminate就永远不可能为真。我跟踪过了,
点击关闭按钮时发出的是WM_CLOSE消息,因此...
而在过程之外,估计Delphi是调用了另一个消息处理过程,因而可以关闭。
难道应该改为:if (Msg.Message <> WM_QUIT) and (Msg.Message <> WM_CLOSE) then ??
Forms.pas我跟踪不进去,改源码也没用。接受现实吧...
 
在 procedure FormClose(Sender: TObject; var Action: TCloseAction);
 
to dana:
请你仔细看一下前面的讨论。
 
你的意思应该是在一个较长的处理过程中使程序仍能相应某些请求,
所以自己在处理中建立了一个消息循环。这样的思路没有什么问题。
但你的意图究竟是那一种呢:
1、收到消息(比如wm_close,关闭窗口)就立即处理吗?还是:
2、等处理循环中的语句执行完一遍再相应消息!
对于第一种情况,应该把响应消息的语句与处理过程分开,使他们可
以并行执行,就是lollman ID:562851中的方法。要是第二种情况,
用最开始的程序应该可以应付了(当然要有“InWroking:=True”),
但要注意在循环中的语句循环一遍不能占用太多时间(也就是把循环
的小时间片分得越细越好),这样才能保证ProcessMessage执行的时
间间隔不至于过大,相应消息才能及时;否则,在响应如wm_close消
息时,会有明显的响应滞后以至于等待响应的感觉。
 
to pxie:
问题是现在在执行循环时根本无法响应FormClose事件,而不是响应慢的问题。
请参看562755一文。
 
ShowModal的实现是这样的:
function TCustomForm.ShowModal: Integer;
...
begin
...
repeat
Application.HandleMessage;
~~~~~~~~~~~~~
if Application.FTerminate then ModalResult := mrCancel else
if ModalResult <> 0 then CloseModal;
until ModalResult <> 0;
...
end;
在代码中,用到了函数HandleMessage,在Borland的文档中,明确指出:
TApplication.HandleMessage
Note:
If the application goes idle, HandleMessage may take a long time
~~~~~~~~~~~~~~~~~~~~
to return. Therefore, do not call HandleMessage when waiting for
~~~~~~~~~
something message-based while priority actions are also being
processed. Instead, call ProcessMessages when processing more
than just messages.

TApplication.ProcessMessages
Note:
ProcessMessages does not allow the application to go idle, whereas
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
HandleMessage does.
~~~~~~~~~~~~~~~~~~~

大家可以看到,这两个函数是有冲突的的。而我们的程序恰好是同时使用到了
这两个函数!我试过这样来做
repeat
//your code
while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
begin
if (Msg.Message <> WM_QUIT) and (Msg.Message <> WM_CLOSE) and not FStop then
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end
else FStop := True;
end;
until FStop;
但是不行。估计是HandleMessage发出运行了Idle,Idle又调用了WaitMessage,
于是PeekMessage总取不出东西,结果就没什么好结果了。

我的建议是:不要使用ShowModal!要实在想用的话,自己写一个不允许切换的
窗口好了。
 
多人接受答案了。
 

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
后退
顶部