这已经在这里讨论过了,但不是在这个细节中。
我在尝试关闭一个非模式子窗体时遇到了问题。我让它通知了父级,但我得到了抽象的错误和其他异常。我做错了什么?父级是必须释放非模态表单,还是再也不尝试通过该变量访问它?
主要形式:
NonModal := NonModalTForm.Create(Self);
NonModal.Callback := Callback;
NonModal.Show;
Procedure TForm.Callback; // called by non-modal form when closing
begin
FreeAndNil(NonModal); // or should this just be NonModal := nil so I don't try to access a dangling pointer?
end;在NonModal.pas中
procedure NonModalTForm.FormClose;
begin
Callback; // calls parent
end;发布于 2010-01-16 08:41:08
您可以从FormClose事件以外的其他地方调用close来关闭表单。在FormClose事件中,只需将操作设置为等于以下值之一:
caFree -处置表单completelycaMinimize -最小化formcaHide -隐藏formcaNone -忽略close例如:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;发布于 2010-01-18 12:40:43
VCL已经有了一种机制,可以在其他组件被释放时通知组件。你可以这样使用它;
type
TfrmParent = class(TForm)
btnShowChild: TButton;
procedure btnShowChildClick(Sender: TObject);
private
FChild: TfrmChild;
public
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
end;
procedure TfrmParent.btnShowChildClick(Sender: TObject);
begin
// Check status of child
if FChild = nil then
begin
// Child does not exist, create it
FChild:= TfrmChild.Create(Application);
FChild.Show;
// Ask Child to notify us when it is destroyed
FChild.FreeNotification(Self);
end
else
begin
// Child already exists
FChild.Show;
end;
end;
procedure TfrmParent.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited;
if (AComponent = FChild) and (Operation = opRemove) then
begin
// FChild is about to be freed, so set reference to Child to nil
FChild:= nil;
end;
end;创建子窗体后,使用创建的窗体的FreeNotification方法进行注册,以便在子窗体被销毁时收到通知。
要对通知做出反应,请覆盖notification方法。在那里,您可以找出哪个组件被销毁,并将其与记住的对子窗体的引用进行比较。收到通知后,只需将对子窗体的引用设置为nil即可。
在子TfrmChild本身中,您不需要做任何其他事情,只需按照skamradt所写的操作:只需在OnClose事件中将参数Actionb设置为caFree即可。
发布于 2010-01-16 07:27:27
如果要在以后显示窗口,请使用Hide。
如果要将其关闭,请使用Close。(关闭主窗口,关闭应用程序)。Close的确切操作取决于表单参数。
查看Close的源代码:
procedure TCustomForm.Close;
var
CloseAction: TCloseAction;
begin
if fsModal in FFormState then
ModalResult := mrCancel
else
if CloseQuery then begin
if FormStyle = fsMDIChild then
if biMinimize in BorderIcons then
CloseAction := caMinimize
else
CloseAction := caNone
else
CloseAction := caHide;
DoClose(CloseAction);
if CloseAction <> caNone then
if Application.MainForm = Self then
Application.Terminate
else if CloseAction = caHide then
Hide
else if CloseAction = caMinimize then
WindowState := wsMinimized
else
Release;
end;
end;但要小心使用free。windows队列中可能会留下一些消息,这可能会导致崩溃。最好使用Release来清理窗口。因为这会在释放消息之前等待消息。
https://stackoverflow.com/questions/2075405
复制相似问题