首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Delphi中关闭非模态窗体

如何在Delphi中关闭非模态窗体
EN

Stack Overflow用户
提问于 2010-01-16 07:20:35
回答 5查看 15.6K关注 0票数 3

这已经在这里讨论过了,但不是在这个细节中。

我在尝试关闭一个非模式子窗体时遇到了问题。我让它通知了父级,但我得到了抽象的错误和其他异常。我做错了什么?父级是必须释放非模态表单,还是再也不尝试通过该变量访问它?

主要形式:

代码语言:javascript
复制
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中

代码语言:javascript
复制
procedure NonModalTForm.FormClose;
begin
  Callback; // calls parent
end;
EN

回答 5

Stack Overflow用户

发布于 2010-01-16 08:41:08

您可以从FormClose事件以外的其他地方调用close来关闭表单。在FormClose事件中,只需将操作设置为等于以下值之一:

  • caFree -处置表单completely
  • caMinimize -最小化form
  • caHide -隐藏form
  • caNone -忽略close

例如:

代码语言:javascript
复制
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;
票数 12
EN

Stack Overflow用户

发布于 2010-01-18 12:40:43

VCL已经有了一种机制,可以在其他组件被释放时通知组件。你可以这样使用它;

代码语言:javascript
复制
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即可。

票数 8
EN

Stack Overflow用户

发布于 2010-01-16 07:27:27

如果要在以后显示窗口,请使用Hide。

如果要将其关闭,请使用Close。(关闭主窗口,关闭应用程序)。Close的确切操作取决于表单参数。

查看Close的源代码:

代码语言:javascript
复制
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来清理窗口。因为这会在释放消息之前等待消息。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2075405

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档