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; 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)

View File

@ -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;