IDE / Designer: fix access violation when switching designer / lfm source. Issue #18506

git-svn-id: trunk@33522 -
This commit is contained in:
juha 2011-11-14 09:32:50 +00:00
parent 24044afdf5
commit ab94abe6d8
2 changed files with 40 additions and 10 deletions

View File

@ -92,6 +92,8 @@ type
FGridColor: TColor;
FLookupRoot: TComponent;
FMediator: TDesignerMediator;
FFreeComponent: boolean;
FProcessingDesignerEvent: Integer;
FOnActivated: TNotifyEvent;
FOnCloseQuery: TNotifyEvent;
FOnShowObjectInspector: TNotifyEvent;
@ -250,7 +252,8 @@ type
constructor Create(TheDesignerForm: TCustomForm;
AControlSelection: TControlSelection);
procedure FreeDesigner(FreeComponent: boolean);
procedure PrepareFreeDesigner(AFreeComponent: boolean);
procedure FinalizeFreeDesigner;
destructor Destroy; override;
procedure Modified; override;
@ -312,6 +315,7 @@ type
property IsControl: Boolean read GetIsControl write SetIsControl;
property LookupRoot: TComponent read FLookupRoot;
property Mediator: TDesignerMediator read FMediator write SetMediator;
property ProcessingDesignerEvent: Integer read FProcessingDesignerEvent;
property OnActivated: TNotifyEvent read FOnActivated write FOnActivated;
property OnCloseQuery: TNotifyEvent read FOnCloseQuery write FOnCloseQuery;
property OnPersistentDeleted: TOnPersistentDeleted
@ -618,7 +622,12 @@ begin
FPopupMenuComponentEditor := nil;
end;
procedure TDesigner.FreeDesigner(FreeComponent: boolean);
procedure TDesigner.PrepareFreeDesigner(AFreeComponent: boolean);
begin
FFreeComponent:=AFreeComponent;
end;
procedure TDesigner.FinalizeFreeDesigner;
var
i: Integer;
begin
@ -634,7 +643,7 @@ begin
end;
if GlobalDesignHook.LookupRoot = FLookupRoot then
GlobalDesignHook.LookupRoot := nil;
if FreeComponent then
if FFreeComponent then
begin
// tell hooks about deleting
for i := FLookupRoot.ComponentCount - 1 downto 0 do
@ -647,7 +656,7 @@ begin
if Mediator<>nil then
Mediator.Designer:=nil;
// free or hide the form
TheFormEditor.DeleteComponent(FLookupRoot,FreeComponent);
TheFormEditor.DeleteComponent(FLookupRoot,FFreeComponent);
FMediator:=nil;
end;
Free;
@ -2199,7 +2208,7 @@ begin
MouseDownComponent:=nil;
MouseDownSender:=nil;
{$IFDEF VerboseDesigner}
DebugLn('[TDesigner.MouseLeftUpOnControl] END');
DebugLn('[TDesigner.MouseUpOnControl] END');
{$ENDIF}
end;
@ -2612,6 +2621,7 @@ begin
Result := false;
if csDesigning in Sender.ComponentState then begin
Result:=true;
Inc(FProcessingDesignerEvent);
case TheMessage.Msg of
LM_PAINT: Result := PaintControl(Sender, TLMPaint(TheMessage));
CN_KEYDOWN,CN_SYSKEYDOWN: KeyDown(Sender,TLMKey(TheMessage));
@ -2631,6 +2641,7 @@ begin
else
Result:=false;
end;
Dec(FProcessingDesignerEvent);
end else begin
if (TheMessage.Msg=LM_PAINT)
or (TheMessage.Msg=CN_KEYDOWN)

View File

@ -633,6 +633,7 @@ type
out aBounds: TRect; out DockSibling: string; out DockAlign: TAlign);
private
FUserInputSinceLastIdle: boolean;
FDesignerToBeFreed: TDesigner; // Will be freed in OnIdle.
FDisplayState: TDisplayState;
FLastFormActivated: TCustomForm;// used to find the last form so you can
// display the correct tab
@ -752,6 +753,8 @@ type
var ComponentUnitInfo: TUnitInfo): TModalResult;
// methods for 'close unit'
procedure FreeDesigner(AnUnitInfo: TUnitInfo; ADesigner: TDesigner;
AFreeComponent: boolean);
function CloseUnitComponent(AnUnitInfo: TUnitInfo; Flags: TCloseFlags
): TModalResult;
function CloseDependingUnitComponents(AnUnitInfo: TUnitInfo;
@ -3747,7 +3750,9 @@ end;
procedure TMainIDE.UpdateIDEComponentPalette;
begin
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;
TComponentPalette(IDEComponentPalette).OnClassSelected := @ComponentPaletteClassSelected;
SetupHints;
@ -6775,6 +6780,7 @@ begin
AnUnitInfo.ComponentName:=NewComponent.Name;
AnUnitInfo.ComponentResourceName:=AnUnitInfo.ComponentName;
DesignerForm := nil;
FLastFormActivated := nil;
if not (ofLoadHiddenResource in OpenFlags) then
begin
DesignerForm := FormEditor1.GetDesignerForm(NewComponent);
@ -7483,6 +7489,17 @@ begin
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
@ -7588,16 +7605,14 @@ begin
{$IFDEF VerboseIDEMultiForm}
DebugLn(['TMainIDE.CloseUnitComponent hiding component and freeing designer: ',AnUnitInfo.Filename,' ',DbgSName(AnUnitInfo.Component)]);
{$ENDIF}
AnUnitInfo.LoadedDesigner:=false;
OldDesigner.FreeDesigner(false);
FreeDesigner(AnUnitInfo, OldDesigner, false);
end else begin
// free designer and design form
{$IFDEF VerboseIDEMultiForm}
DebugLn(['TMainIDE.CloseUnitComponent freeing component and designer: ',AnUnitInfo.Filename,' ',DbgSName(AnUnitInfo.Component)]);
{$ENDIF}
try
AnUnitInfo.LoadedDesigner:=false;
OldDesigner.FreeDesigner(true);
FreeDesigner(AnUnitInfo, OldDesigner, true);
finally
AnUnitInfo.Component:=nil;
end;
@ -17061,6 +17076,10 @@ begin
ExternalTools.FreeStoppedProcesses;
if (SplashForm<>nil) then FreeThenNil(SplashForm);
if Assigned(FDesignerToBeFreed) then begin
FDesignerToBeFreed.FinalizeFreeDesigner;
FDesignerToBeFreed:=Nil;
end;
if FUserInputSinceLastIdle then
begin
FUserInputSinceLastIdle:=false;