Delphi 7中Application.OnActivate的意外行为

7

我编写了一个D7应用程序来测试Application.OnActivate的行为。

以下是相关部分:

procedure TMainForm.FormCreate (Sender: TObject);
begin
Memo1.Lines.Add (IntToStr (Memo1.Lines.Count + 1) + ' - MainForm.FormCreate - Begin');

  Application.OnActivate := AppActivate;

Memo1.Lines.Add (IntToStr (Memo1.Lines.Count + 1) + ' - MainForm.FormCreate - End');
end;


procedure TMainForm.AppActivate (Sender: TObject);
begin
Memo1.Lines.Add (IntToStr (Memo1.Lines.Count + 1) + ' - MainForm.AppActivate - Begin');

  ShowWidthsHeights (Sender);

Memo1.Lines.Add (IntToStr (Memo1.Lines.Count + 1) + ' - MainForm.AppActivate - End');
end;


procedure TMainForm.ShowWidthsHeights (Sender: TObject);

begin
Memo1.Lines.Add (IntToStr (Memo1.Lines.Count + 1) + ' - MainForm.ShowWidthsHeights -     Begin');

Memo1.Lines.Add (IntToStr (Memo1.Lines.Count + 1) + ' - MainForm.ShowWidthsHeights -     End');
end;

启动应用程序后,Memo1的内容为:
1 - MainForm.FormCreate - 开始
2 - MainForm.FormCreate - 结束
3 - MainForm.AppActivate - 开始
4 - MainForm.ShowWidthsHeights - 开始
5 - MainForm.ShowWidthsHeights - 结束
6 - MainForm.AppActivate - 结束

没错。

但如果我点击任务栏中的一个快捷方式,则会向Memo1添加这4行:
7 - MainForm.AppActivate - 开始
8 - MainForm.ShowWidthsHeights - 开始
9 - MainForm.ShowWidthsHeights - 结束
10 - MainForm.AppActivate - 结束

为什么D7会这样做?
我的应用程序还没有被激活,相反,它已被停用!


为了测试是否触发了Application.OnDeactivate事件,我添加了此事件处理程序:

procedure TMainForm.AppDeactivate(Sender: TObject);
begin
Memo1.Lines.Add (IntToStr (Memo1.Lines.Count + 1) + ' - MainForm.AppDeactivate - Begin');

Memo1.Lines.Add (IntToStr (Memo1.Lines.Count + 1) + ' - MainForm.AppDeactivate - End');
end;

并在TMainForm.FormCreate中添加了以下语句:

Application.OnDeactivate := AppDeactivate;  

启动应用程序后,Memo1中包含与原始情况相同的6行内容,但是单击任务栏中的快捷方式会在Memo1中添加8行额外的内容:

7 - MainForm.AppDeactivate - Begin  
8 - MainForm.AppDeactivate - End  
9 - MainForm.AppActivate - Begin  
10 - MainForm.ShowWidthsHeights - Begin  
11 - MainForm.ShowWidthsHeights - End  
12 - MainForm.AppActivate - End  
13 - MainForm.AppDeactivate - Begin  
14 - MainForm.AppDeactivate - End  

我的应用程序被停用,然后重新启用,然后再次停用!


这相当令人困惑!


1
Delphi仅向您反映Windows发送给您的应用程序的'WM_ACTIVATEAPP'消息。我不知道为什么Windows会这样做。 - David Heffernan
你确定当你第一次点击任务栏按钮时(这可能会最小化窗体),7到10是否已经被记录,还是当你再次点击以查看备忘录时才记录?你可以使用OutputDebugString和“事件日志”(ctrl+alt+v)而不是记录备忘录来确保。 - Sertac Akyuz
1
@Sertac 是的,我已经检查过了。它与问题描述完全一致。 - David Heffernan
嗯,我无法重现这个问题。当我点击任务栏时,只会出现一个很好的应用程序停用。 我怀疑楼主在做其他事情(双击)。 - Marck
1个回答

1

正如David的评论所述,它反映了接收WM_ACTIVATE消息。http://msdn.microsoft.com/en-us/library/windows/desktop/ms632614(v=vs.85).aspx给出了答案:

当属于与活动窗口不同的应用程序的窗口即将被激活时发送。该消息发送到正在激活其窗口的应用程序以及正在停用其窗口的应用程序。

消息的参数进一步解释:

wParam:

指示窗口是否正在被激活或停用。如果窗口正在被激活,则此参数为TRUE;如果窗口正在被停用,则此参数为FALSE。


1
这并没有解释任务栏按钮的点击是如何先发送一个失活信号,紧接着又发送一个激活信号的。 - David Heffernan
1
David,你是对的。@Roald,为了消除混淆,有一个WM_ACTIVATEAPP信号激活和去激活,但是有两个不同的Delphi事件。Delphi库捕获WM_ACTIVATEAPP并根据wParam触发CM_ACTIVATE或CM_DEACTIVATE;然后由TApplication捕获以触发onActivate或onDeactivate事件。 - PA.
仍然有人为一个回答进行点赞,尽管该回答未能解决所提出的问题。唉…… - David Heffernan
@PA " (...) 并根据 wParam 的值触发 CM_ACTIVATE 或 CM_DEACTIVATE 事件;然后 TApplication 捕获这些事件并触发 onActivate 或 onDeactivate 事件。" 这是 D7 实际上的行为还是应该的行为?似乎 D7 总是触发 OnActivate 事件,无论 wParam 的值如何。 - Ruud Schmeitz
@Athena 是的,Windows 发送了一个停用消息,然后是一个激活消息。问题是为什么会这样做。Delphi 正确地解释了 WM_ACTIVATEAPP。这个问题完全与 Windows 有关。 - David Heffernan
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接