Unexpected behaviour of Application.OnActivate in Delphi 7
Asked Answered
V

1

7

I wrote a D7 application to test the behaviour of Application.OnActivate .
This is the relevant part :

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;

After starting the application , the content of Memo1 is :
1 - MainForm.FormCreate - Begin
2 - MainForm.FormCreate - End
3 - MainForm.AppActivate - Begin
4 - MainForm.ShowWidthsHeights - Begin
5 - MainForm.ShowWidthsHeights - End
6 - MainForm.AppActivate - End

That is correct .

But if I then click on a shortcut in the taskbar , these 4 lines are added to Memo1 :
7 - MainForm.AppActivate - Begin
8 - MainForm.ShowWidthsHeights - Begin
9 - MainForm.ShowWidthsHeights - End
10 - MainForm.AppActivate - End

Why does D7 do that ?
My application hasn't been activated , on the contrary , it has been deactivated !


To test if the Application.OnDeactivate event is also fired , I added this event handler :

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;

and added this statement to TMainForm.FormCreate :

Application.OnDeactivate := AppDeactivate;  

After starting the application , Memo1 contained the same 6 lines as in the original case , but clicking on a shortcut in the taskbar resulted in 8 extra lines in Memo1 :

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  

So , my application gets deactivated , then activated , and then deactivated again !
That's quite confusing !

Vasoconstrictor answered 27/6, 2012 at 9:38 Comment(4)
Delphi is simply reflecting to you the WM_ACTIVATEAPP message that Windows sends to your app. Why Windows does so, I do not know.Bise
Are you positive that 7 through 10 is logged when you first click on the taskbar button (which would presumably minimize the form), or when you click again to see the memo? You can use OutputDebugString and the 'Event Log' (ctrl+alt+v) instead of logging to the memo to be sure.Goliath
@Sertac Yeah, I checked this already. It is exactly as described in the Q.Bise
Well, I can't reproduce it. I get a nice app-deactivate and that's it when I click on the taskbar. I suspect the OP is doing something else (double-clicking).Beatify
S
1

As the comment of David already stated, it is reflecting the receiving of the WM_ACTIVATE message. http://msdn.microsoft.com/en-us/library/windows/desktop/ms632614(v=vs.85).aspx gives the answer:

Sent when a window belonging to a different application than the active window is about to be activated. The message is sent to the application whose window is being activated and to the application whose window is being deactivated.

and the parameters of the message explain further:

wParam:

Indicates whether the window is being activated or deactivated. This parameter is TRUE if the window is being activated; it is FALSE if the window is being deactivated.

Soupandfish answered 27/6, 2012 at 12:11 Comment(7)
That doesn't explain the the taskbar button click sends a deactivate immediately followed by an activate.Bise
David, you are right. @Roald, to clear confusion, there is one WM_ACTIVATEAPP that signals activation and deactivation, but there are two different Delphi events. The Delphi library captures WM_ACTIVATEAPP and depending on wParam it then fires either a CM_ACTIVATE or a CM_DEACTIVATE; which in turn are captured by TApplication to fire the onActivate or onDeactivate events.Pleasure
And still the up-votes come in for an answer that fails to address the question that was asked. Sigh.....Bise
@David Heffernan "That doesn't explain the the taskbar button click sends a deactivate immediately followed by an activate." I don't think Windows sent a deactivate message to my application . According to the description of the WM_ACTIVATEAPP message (@Roald -Thanks for the link and the quotes !) , Windows also sends the WM_ACTIVATEAPP message "to the application whose window is being deactivated" . That would explain why the D7 Application.OnActivate event is fired again (adding line 7 through 10 to Memo1) .Vasoconstrictor
@PA "(...) and depending on wParam it then fires either a CM_ACTIVATE or a CM_DEACTIVATE; which in turn are captured by TApplication to fire the onActivate or onDeactivate events." Is this what D7 actually does , or what it should do ? It seems that D7 always fires the OnActivate event , no matter the value of wParam .Vasoconstrictor
@Athena Yes, windows sent a deactivate message, and then an activate. The question is why it does that. Delphi interprets WM_ACTIVATEAPP correctly. This issue is all about Windows.Bise
@Athena, this is what D7 does.Pleasure

© 2022 - 2024 — McMap. All rights reserved.