mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-24 12:59:39 +02:00
IDE / Designer: fix access violation when switching designer / lfm source. Issue #18506
git-svn-id: trunk@33522 -
This commit is contained in:
parent
24044afdf5
commit
ab94abe6d8
@ -92,6 +92,8 @@ type
|
|||||||
FGridColor: TColor;
|
FGridColor: TColor;
|
||||||
FLookupRoot: TComponent;
|
FLookupRoot: TComponent;
|
||||||
FMediator: TDesignerMediator;
|
FMediator: TDesignerMediator;
|
||||||
|
FFreeComponent: boolean;
|
||||||
|
FProcessingDesignerEvent: Integer;
|
||||||
FOnActivated: TNotifyEvent;
|
FOnActivated: TNotifyEvent;
|
||||||
FOnCloseQuery: TNotifyEvent;
|
FOnCloseQuery: TNotifyEvent;
|
||||||
FOnShowObjectInspector: TNotifyEvent;
|
FOnShowObjectInspector: TNotifyEvent;
|
||||||
@ -250,7 +252,8 @@ type
|
|||||||
|
|
||||||
constructor Create(TheDesignerForm: TCustomForm;
|
constructor Create(TheDesignerForm: TCustomForm;
|
||||||
AControlSelection: TControlSelection);
|
AControlSelection: TControlSelection);
|
||||||
procedure FreeDesigner(FreeComponent: boolean);
|
procedure PrepareFreeDesigner(AFreeComponent: boolean);
|
||||||
|
procedure FinalizeFreeDesigner;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
|
||||||
procedure Modified; override;
|
procedure Modified; override;
|
||||||
@ -312,6 +315,7 @@ type
|
|||||||
property IsControl: Boolean read GetIsControl write SetIsControl;
|
property IsControl: Boolean read GetIsControl write SetIsControl;
|
||||||
property LookupRoot: TComponent read FLookupRoot;
|
property LookupRoot: TComponent read FLookupRoot;
|
||||||
property Mediator: TDesignerMediator read FMediator write SetMediator;
|
property Mediator: TDesignerMediator read FMediator write SetMediator;
|
||||||
|
property ProcessingDesignerEvent: Integer read FProcessingDesignerEvent;
|
||||||
property OnActivated: TNotifyEvent read FOnActivated write FOnActivated;
|
property OnActivated: TNotifyEvent read FOnActivated write FOnActivated;
|
||||||
property OnCloseQuery: TNotifyEvent read FOnCloseQuery write FOnCloseQuery;
|
property OnCloseQuery: TNotifyEvent read FOnCloseQuery write FOnCloseQuery;
|
||||||
property OnPersistentDeleted: TOnPersistentDeleted
|
property OnPersistentDeleted: TOnPersistentDeleted
|
||||||
@ -618,7 +622,12 @@ begin
|
|||||||
FPopupMenuComponentEditor := nil;
|
FPopupMenuComponentEditor := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TDesigner.FreeDesigner(FreeComponent: boolean);
|
procedure TDesigner.PrepareFreeDesigner(AFreeComponent: boolean);
|
||||||
|
begin
|
||||||
|
FFreeComponent:=AFreeComponent;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TDesigner.FinalizeFreeDesigner;
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
@ -634,7 +643,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
if GlobalDesignHook.LookupRoot = FLookupRoot then
|
if GlobalDesignHook.LookupRoot = FLookupRoot then
|
||||||
GlobalDesignHook.LookupRoot := nil;
|
GlobalDesignHook.LookupRoot := nil;
|
||||||
if FreeComponent then
|
if FFreeComponent then
|
||||||
begin
|
begin
|
||||||
// tell hooks about deleting
|
// tell hooks about deleting
|
||||||
for i := FLookupRoot.ComponentCount - 1 downto 0 do
|
for i := FLookupRoot.ComponentCount - 1 downto 0 do
|
||||||
@ -647,7 +656,7 @@ begin
|
|||||||
if Mediator<>nil then
|
if Mediator<>nil then
|
||||||
Mediator.Designer:=nil;
|
Mediator.Designer:=nil;
|
||||||
// free or hide the form
|
// free or hide the form
|
||||||
TheFormEditor.DeleteComponent(FLookupRoot,FreeComponent);
|
TheFormEditor.DeleteComponent(FLookupRoot,FFreeComponent);
|
||||||
FMediator:=nil;
|
FMediator:=nil;
|
||||||
end;
|
end;
|
||||||
Free;
|
Free;
|
||||||
@ -2199,7 +2208,7 @@ begin
|
|||||||
MouseDownComponent:=nil;
|
MouseDownComponent:=nil;
|
||||||
MouseDownSender:=nil;
|
MouseDownSender:=nil;
|
||||||
{$IFDEF VerboseDesigner}
|
{$IFDEF VerboseDesigner}
|
||||||
DebugLn('[TDesigner.MouseLeftUpOnControl] END');
|
DebugLn('[TDesigner.MouseUpOnControl] END');
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2612,6 +2621,7 @@ begin
|
|||||||
Result := false;
|
Result := false;
|
||||||
if csDesigning in Sender.ComponentState then begin
|
if csDesigning in Sender.ComponentState then begin
|
||||||
Result:=true;
|
Result:=true;
|
||||||
|
Inc(FProcessingDesignerEvent);
|
||||||
case TheMessage.Msg of
|
case TheMessage.Msg of
|
||||||
LM_PAINT: Result := PaintControl(Sender, TLMPaint(TheMessage));
|
LM_PAINT: Result := PaintControl(Sender, TLMPaint(TheMessage));
|
||||||
CN_KEYDOWN,CN_SYSKEYDOWN: KeyDown(Sender,TLMKey(TheMessage));
|
CN_KEYDOWN,CN_SYSKEYDOWN: KeyDown(Sender,TLMKey(TheMessage));
|
||||||
@ -2631,6 +2641,7 @@ begin
|
|||||||
else
|
else
|
||||||
Result:=false;
|
Result:=false;
|
||||||
end;
|
end;
|
||||||
|
Dec(FProcessingDesignerEvent);
|
||||||
end else begin
|
end else begin
|
||||||
if (TheMessage.Msg=LM_PAINT)
|
if (TheMessage.Msg=LM_PAINT)
|
||||||
or (TheMessage.Msg=CN_KEYDOWN)
|
or (TheMessage.Msg=CN_KEYDOWN)
|
||||||
|
29
ide/main.pp
29
ide/main.pp
@ -633,6 +633,7 @@ type
|
|||||||
out aBounds: TRect; out DockSibling: string; out DockAlign: TAlign);
|
out aBounds: TRect; out DockSibling: string; out DockAlign: TAlign);
|
||||||
private
|
private
|
||||||
FUserInputSinceLastIdle: boolean;
|
FUserInputSinceLastIdle: boolean;
|
||||||
|
FDesignerToBeFreed: TDesigner; // Will be freed in OnIdle.
|
||||||
FDisplayState: TDisplayState;
|
FDisplayState: TDisplayState;
|
||||||
FLastFormActivated: TCustomForm;// used to find the last form so you can
|
FLastFormActivated: TCustomForm;// used to find the last form so you can
|
||||||
// display the correct tab
|
// display the correct tab
|
||||||
@ -752,6 +753,8 @@ type
|
|||||||
var ComponentUnitInfo: TUnitInfo): TModalResult;
|
var ComponentUnitInfo: TUnitInfo): TModalResult;
|
||||||
|
|
||||||
// methods for 'close unit'
|
// methods for 'close unit'
|
||||||
|
procedure FreeDesigner(AnUnitInfo: TUnitInfo; ADesigner: TDesigner;
|
||||||
|
AFreeComponent: boolean);
|
||||||
function CloseUnitComponent(AnUnitInfo: TUnitInfo; Flags: TCloseFlags
|
function CloseUnitComponent(AnUnitInfo: TUnitInfo; Flags: TCloseFlags
|
||||||
): TModalResult;
|
): TModalResult;
|
||||||
function CloseDependingUnitComponents(AnUnitInfo: TUnitInfo;
|
function CloseDependingUnitComponents(AnUnitInfo: TUnitInfo;
|
||||||
@ -3747,7 +3750,9 @@ end;
|
|||||||
procedure TMainIDE.UpdateIDEComponentPalette;
|
procedure TMainIDE.UpdateIDEComponentPalette;
|
||||||
begin
|
begin
|
||||||
IDEComponentPalette.HideControls:=(FLastFormActivated<>nil)
|
IDEComponentPalette.HideControls:=(FLastFormActivated<>nil)
|
||||||
and (not (TDesigner(FLastFormActivated.Designer).LookupRoot is TControl));
|
and (FLastFormActivated.Designer<>nil)
|
||||||
|
and (TDesigner(FLastFormActivated.Designer).LookupRoot<>nil)
|
||||||
|
and not ((FLastFormActivated.Designer as TDesigner).LookupRoot is TControl);
|
||||||
IDEComponentPalette.UpdateVisible;
|
IDEComponentPalette.UpdateVisible;
|
||||||
TComponentPalette(IDEComponentPalette).OnClassSelected := @ComponentPaletteClassSelected;
|
TComponentPalette(IDEComponentPalette).OnClassSelected := @ComponentPaletteClassSelected;
|
||||||
SetupHints;
|
SetupHints;
|
||||||
@ -6775,6 +6780,7 @@ begin
|
|||||||
AnUnitInfo.ComponentName:=NewComponent.Name;
|
AnUnitInfo.ComponentName:=NewComponent.Name;
|
||||||
AnUnitInfo.ComponentResourceName:=AnUnitInfo.ComponentName;
|
AnUnitInfo.ComponentResourceName:=AnUnitInfo.ComponentName;
|
||||||
DesignerForm := nil;
|
DesignerForm := nil;
|
||||||
|
FLastFormActivated := nil;
|
||||||
if not (ofLoadHiddenResource in OpenFlags) then
|
if not (ofLoadHiddenResource in OpenFlags) then
|
||||||
begin
|
begin
|
||||||
DesignerForm := FormEditor1.GetDesignerForm(NewComponent);
|
DesignerForm := FormEditor1.GetDesignerForm(NewComponent);
|
||||||
@ -7483,6 +7489,17 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TMainIDE.FreeDesigner(AnUnitInfo: TUnitInfo; ADesigner: TDesigner;
|
||||||
|
AFreeComponent: boolean);
|
||||||
|
begin
|
||||||
|
AnUnitInfo.LoadedDesigner:=false;
|
||||||
|
ADesigner.PrepareFreeDesigner(AFreeComponent);
|
||||||
|
if ADesigner.ProcessingDesignerEvent > 0 then
|
||||||
|
FDesignerToBeFreed:=ADesigner // Free it later on idle time.
|
||||||
|
else
|
||||||
|
ADesigner.FinalizeFreeDesigner; // Free it now.
|
||||||
|
end;
|
||||||
|
|
||||||
{-------------------------------------------------------------------------------
|
{-------------------------------------------------------------------------------
|
||||||
function TMainIDE.CloseUnitComponent
|
function TMainIDE.CloseUnitComponent
|
||||||
|
|
||||||
@ -7588,16 +7605,14 @@ begin
|
|||||||
{$IFDEF VerboseIDEMultiForm}
|
{$IFDEF VerboseIDEMultiForm}
|
||||||
DebugLn(['TMainIDE.CloseUnitComponent hiding component and freeing designer: ',AnUnitInfo.Filename,' ',DbgSName(AnUnitInfo.Component)]);
|
DebugLn(['TMainIDE.CloseUnitComponent hiding component and freeing designer: ',AnUnitInfo.Filename,' ',DbgSName(AnUnitInfo.Component)]);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
AnUnitInfo.LoadedDesigner:=false;
|
FreeDesigner(AnUnitInfo, OldDesigner, false);
|
||||||
OldDesigner.FreeDesigner(false);
|
|
||||||
end else begin
|
end else begin
|
||||||
// free designer and design form
|
// free designer and design form
|
||||||
{$IFDEF VerboseIDEMultiForm}
|
{$IFDEF VerboseIDEMultiForm}
|
||||||
DebugLn(['TMainIDE.CloseUnitComponent freeing component and designer: ',AnUnitInfo.Filename,' ',DbgSName(AnUnitInfo.Component)]);
|
DebugLn(['TMainIDE.CloseUnitComponent freeing component and designer: ',AnUnitInfo.Filename,' ',DbgSName(AnUnitInfo.Component)]);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
try
|
try
|
||||||
AnUnitInfo.LoadedDesigner:=false;
|
FreeDesigner(AnUnitInfo, OldDesigner, true);
|
||||||
OldDesigner.FreeDesigner(true);
|
|
||||||
finally
|
finally
|
||||||
AnUnitInfo.Component:=nil;
|
AnUnitInfo.Component:=nil;
|
||||||
end;
|
end;
|
||||||
@ -17061,6 +17076,10 @@ begin
|
|||||||
ExternalTools.FreeStoppedProcesses;
|
ExternalTools.FreeStoppedProcesses;
|
||||||
if (SplashForm<>nil) then FreeThenNil(SplashForm);
|
if (SplashForm<>nil) then FreeThenNil(SplashForm);
|
||||||
|
|
||||||
|
if Assigned(FDesignerToBeFreed) then begin
|
||||||
|
FDesignerToBeFreed.FinalizeFreeDesigner;
|
||||||
|
FDesignerToBeFreed:=Nil;
|
||||||
|
end;
|
||||||
if FUserInputSinceLastIdle then
|
if FUserInputSinceLastIdle then
|
||||||
begin
|
begin
|
||||||
FUserInputSinceLastIdle:=false;
|
FUserInputSinceLastIdle:=false;
|
||||||
|
Loading…
Reference in New Issue
Block a user