mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-22 17:59:22 +02:00
lcl: don't call Activate, Deactivate for TForm on WM_ACTIVATE message - since it also means activate/deactivate on application activation/deactivation. Use Screen.FocusedForm to track form activation/deactivation. Send CM_ACTIVATE, CM_DEACTIVATE instead of direct event calling. (this is VCL compatible and fixes issue #0015054)
git-svn-id: trunk@25274 -
This commit is contained in:
parent
b07cd9b4f5
commit
a12d403ae0
@ -488,6 +488,8 @@ type
|
|||||||
procedure CMAppShowMenuGlyphChanged(var Message: TLMessage); message CM_APPSHOWMENUGLYPHCHANGED;
|
procedure CMAppShowMenuGlyphChanged(var Message: TLMessage); message CM_APPSHOWMENUGLYPHCHANGED;
|
||||||
procedure CMIconChanged(var Message: TLMessage); message CM_ICONCHANGED;
|
procedure CMIconChanged(var Message: TLMessage); message CM_ICONCHANGED;
|
||||||
procedure CMRelease(var Message: TLMessage); message CM_RELEASE;
|
procedure CMRelease(var Message: TLMessage); message CM_RELEASE;
|
||||||
|
procedure CMActivate(var Message: TLMessage); message CM_ACTIVATE;
|
||||||
|
procedure CMDeactivate(var Message: TLMessage); message CM_DEACTIVATE;
|
||||||
procedure AddHandler(HandlerType: TFormHandlerType;
|
procedure AddHandler(HandlerType: TFormHandlerType;
|
||||||
const Handler: TMethod; AsLast: Boolean);
|
const Handler: TMethod; AsLast: Boolean);
|
||||||
procedure RemoveHandler(HandlerType: TFormHandlerType;
|
procedure RemoveHandler(HandlerType: TFormHandlerType;
|
||||||
@ -941,6 +943,7 @@ type
|
|||||||
function GetWidth : Integer;
|
function GetWidth : Integer;
|
||||||
procedure AddForm(AForm: TCustomForm);
|
procedure AddForm(AForm: TCustomForm);
|
||||||
procedure RemoveForm(AForm: TCustomForm);
|
procedure RemoveForm(AForm: TCustomForm);
|
||||||
|
function SetFocusedForm(AForm: TCustomForm): Boolean;
|
||||||
procedure SetCursor(const AValue: TCursor);
|
procedure SetCursor(const AValue: TCursor);
|
||||||
procedure SetCursors(AIndex: Integer; const AValue: HCURSOR);
|
procedure SetCursors(AIndex: Integer; const AValue: HCURSOR);
|
||||||
procedure SetHintFont(const AValue: TFont);
|
procedure SetHintFont(const AValue: TFont);
|
||||||
|
@ -483,8 +483,8 @@ begin
|
|||||||
if (FormStyle <> fsMDIForm) or (csDesigning in ComponentState) then
|
if (FormStyle <> fsMDIForm) or (csDesigning in ComponentState) then
|
||||||
SetActive(Message.Active);
|
SetActive(Message.Active);
|
||||||
|
|
||||||
Activate;
|
if Application <> nil then
|
||||||
if Application <> nil then Application.Activate;
|
Application.Activate;
|
||||||
// The button reappears in some situations (e.g. when the window gets the
|
// The button reappears in some situations (e.g. when the window gets the
|
||||||
//"urgency" flag) so we hide it again here.
|
//"urgency" flag) so we hide it again here.
|
||||||
// This is the most important place to invoke UpdateShowInTaskBar, since
|
// This is the most important place to invoke UpdateShowInTaskBar, since
|
||||||
@ -507,12 +507,11 @@ procedure TCustomForm.WMDeactivate(var Message : TLMActivate);
|
|||||||
begin
|
begin
|
||||||
FActive:=false;
|
FActive:=false;
|
||||||
{$IFDEF EnableAsyncDeactivate}
|
{$IFDEF EnableAsyncDeactivate}
|
||||||
Deactivate;
|
|
||||||
if Application<>nil then
|
if Application<>nil then
|
||||||
Application.QueueAsyncCall(@Application.Deactivate,0);
|
Application.QueueAsyncCall(@Application.Deactivate,0);
|
||||||
{$ELSE}
|
{$ELSE}
|
||||||
if Application<>nil then Application.Deactivate;
|
if Application<>nil then
|
||||||
Deactivate;
|
Application.Deactivate;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -741,6 +740,16 @@ begin
|
|||||||
Free;
|
Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TCustomForm.CMActivate(var Message: TLMessage);
|
||||||
|
begin
|
||||||
|
Activate;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TCustomForm.CMDeactivate(var Message: TLMessage);
|
||||||
|
begin
|
||||||
|
Deactivate;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TCustomForm.AddHandler(HandlerType: TFormHandlerType;
|
procedure TCustomForm.AddHandler(HandlerType: TFormHandlerType;
|
||||||
const Handler: TMethod; AsLast: Boolean);
|
const Handler: TMethod; AsLast: Boolean);
|
||||||
begin
|
begin
|
||||||
@ -2132,17 +2141,46 @@ end;
|
|||||||
------------------------------------------------------------------------------}
|
------------------------------------------------------------------------------}
|
||||||
function TCustomForm.SetFocusedControl(Control: TWinControl): Boolean;
|
function TCustomForm.SetFocusedControl(Control: TWinControl): Boolean;
|
||||||
|
|
||||||
function NextChildControl(CurParent, Target: TWinControl): TWinControl; inline;
|
function SendEnterExitLoop: Boolean;
|
||||||
|
|
||||||
|
function NextChildControl(CurParent, Target: TWinControl): TWinControl; inline;
|
||||||
|
begin
|
||||||
|
while Target.Parent <> CurParent do
|
||||||
|
Target := Target.Parent;
|
||||||
|
Result := Target;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
LastState: TFocusState;
|
||||||
begin
|
begin
|
||||||
while Target.Parent <> CurParent do
|
// send cm_exit, cm_enter messages
|
||||||
Target := Target.Parent;
|
// cm_exit must be sent to all controls from lastfocusedcontrol to the first parent which contains control
|
||||||
Result := Target;
|
// cm_enter must be sent from the control we stoped up to control
|
||||||
|
// if during this loop something happens with focus (another control or form has aquired it) we need to stop it
|
||||||
|
|
||||||
|
while not FLastFocusedControl.ContainsControl(Control) do
|
||||||
|
begin
|
||||||
|
LastState := SaveFocusState;
|
||||||
|
FLastFocusedControl.Perform(CM_EXIT, 0, 0);
|
||||||
|
if SaveFocusState <> LastState then
|
||||||
|
Exit(False);
|
||||||
|
FLastFocusedControl := FLastFocusedControl.Parent;
|
||||||
|
end;
|
||||||
|
|
||||||
|
while FLastFocusedControl <> Control do
|
||||||
|
begin
|
||||||
|
FLastFocusedControl := NextChildControl(FLastFocusedControl, Control);
|
||||||
|
LastState := SaveFocusState;
|
||||||
|
FLastFocusedControl.Perform(CM_ENTER, 0, 0);
|
||||||
|
if SaveFocusState <> LastState then
|
||||||
|
Exit(False);
|
||||||
|
end;
|
||||||
|
Result := True;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
ParentForm: TCustomForm;
|
ParentForm: TCustomForm;
|
||||||
CurControl: TWinControl;
|
CurControl: TWinControl;
|
||||||
LastState: TFocusState;
|
|
||||||
begin
|
begin
|
||||||
LastFocusedControl := Control;
|
LastFocusedControl := Control;
|
||||||
Result := False;
|
Result := False;
|
||||||
@ -2192,7 +2230,8 @@ begin
|
|||||||
begin
|
begin
|
||||||
Control.ControlState := Control.ControlState + [csFocusing];
|
Control.ControlState := Control.ControlState + [csFocusing];
|
||||||
try
|
try
|
||||||
Screen.FFocusedForm := Self;
|
if not Screen.SetFocusedForm(Self) then
|
||||||
|
Exit;
|
||||||
// update ActiveControls of all parent forms
|
// update ActiveControls of all parent forms
|
||||||
CurControl := Control.Parent;
|
CurControl := Control.Parent;
|
||||||
while CurControl <> nil do
|
while CurControl <> nil do
|
||||||
@ -2201,33 +2240,10 @@ begin
|
|||||||
TCustomForm(CurControl).FActiveControl := Control;
|
TCustomForm(CurControl).FActiveControl := Control;
|
||||||
CurControl := CurControl.Parent;
|
CurControl := CurControl.Parent;
|
||||||
end;
|
end;
|
||||||
|
Result := SendEnterExitLoop;
|
||||||
// send cm_exit, cm_enter messages
|
|
||||||
// cm_exit must be sent to all controls from lastfocusedcontrol to the first parent which contains control
|
|
||||||
// cm_enter must be sent from the control we stoped up to control
|
|
||||||
// if during this loop something happens with focus (another control or form has aquired it) we need to stop it
|
|
||||||
|
|
||||||
while not FLastFocusedControl.ContainsControl(Control) do
|
|
||||||
begin
|
|
||||||
LastState := SaveFocusState;
|
|
||||||
FLastFocusedControl.Perform(CM_EXIT, 0, 0);
|
|
||||||
if SaveFocusState <> LastState then
|
|
||||||
Exit;
|
|
||||||
FLastFocusedControl := FLastFocusedControl.Parent;
|
|
||||||
end;
|
|
||||||
|
|
||||||
while FLastFocusedControl <> Control do
|
|
||||||
begin
|
|
||||||
FLastFocusedControl := NextChildControl(FLastFocusedControl, Control);
|
|
||||||
LastState := SaveFocusState;
|
|
||||||
FLastFocusedControl.Perform(CM_ENTER, 0, 0);
|
|
||||||
if SaveFocusState <> LastState then
|
|
||||||
Exit;
|
|
||||||
end;
|
|
||||||
finally
|
finally
|
||||||
Control.ControlState := Control.ControlState - [csFocusing];
|
Control.ControlState := Control.ControlState - [csFocusing];
|
||||||
end;
|
end;
|
||||||
Result := True;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -763,6 +763,34 @@ begin
|
|||||||
Application.UpdateVisible;
|
Application.UpdateVisible;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TScreen.SetFocusedForm(AForm: TCustomForm): Boolean;
|
||||||
|
var
|
||||||
|
LastState: TFocusState;
|
||||||
|
begin
|
||||||
|
// result determins if focused state has changed during Activate/Deactivate events
|
||||||
|
// if so we should return False (since activate/deactivate failed)
|
||||||
|
Result := True;
|
||||||
|
if FFocusedForm <> AForm then
|
||||||
|
begin
|
||||||
|
// send deactivate to the previosly focused form
|
||||||
|
LastState := SaveFocusState;
|
||||||
|
if FFocusedForm <> nil then
|
||||||
|
FFocusedForm.Perform(CM_DEACTIVATE, 0, 0);
|
||||||
|
if SaveFocusState <> LastState then
|
||||||
|
begin
|
||||||
|
FFocusedForm := nil;
|
||||||
|
Exit(False);
|
||||||
|
end;
|
||||||
|
// send activate to the newly focused form
|
||||||
|
FFocusedForm := AForm;
|
||||||
|
LastState := SaveFocusState;
|
||||||
|
if FFocusedForm <> nil then
|
||||||
|
FFocusedForm.Perform(CM_ACTIVATE, 0, 0);
|
||||||
|
if SaveFocusState <> LastState then
|
||||||
|
Exit(False);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
{------------------------------------------------------------------------------
|
{------------------------------------------------------------------------------
|
||||||
procedure TScreen.SetCursor(const AValue: TCursor);
|
procedure TScreen.SetCursor(const AValue: TCursor);
|
||||||
------------------------------------------------------------------------------}
|
------------------------------------------------------------------------------}
|
||||||
|
Loading…
Reference in New Issue
Block a user