如何隐藏主窗体而不是关闭它?

3
如果用户在我的主窗体上单击X,我希望窗体隐藏而不是关闭。这听起来像是使用OnClose表单事件的工作:
使用OnClose在窗体关闭时执行特殊处理。OnClose事件指定在窗体即将关闭时调用哪个事件处理程序。由OnClose指定的处理程序可能会检查数据输入窗体中所有字段是否具有有效内容,然后才允许窗体关闭。
通过Close方法或当用户选择关闭窗口的系统菜单时,窗体被关闭。
TCloseEvent类型指向处理窗体关闭的方法。Action参数的值确定窗体是否实际关闭。以下是Action的可能值:
- caNone:不允许关闭窗体,因此什么也不会发生。 - caHide:窗体未关闭,而是隐藏了起来。您的应用程序仍然可以访问一个隐藏的窗体。 - caFree:窗体已关闭,窗体分配的所有内存都已释放。 - caMinimize:窗体被最小化,而不是关闭。这是MDI子窗体的默认操作。
我在一个空应用程序中测试了一下。
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    Action := caHide;
end;

现在,当我点击X时,表单不再隐藏,而是关闭应用程序:

enter image description here

这听起来像是使用OnClose事件完成的任务...

额外阅读

Vcl.Forms.pas

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
      begin
         if Application.MainForm = Self then //Borland doesn't hate developers; it just hates me
            Application.Terminate
         else if CloseAction = caHide then   
            Hide
         else if CloseAction = caMinimize then 
            WindowState := wsMinimized
         else 
            Release;
      end;
   end;
end;

额外阅读


2
主窗体不同。任何次要窗体都将遵守规定。 - Sertac Akyuz
2个回答

11

当用户关闭一个窗口时,它会收到一个WM_CLOSE消息,这会触发TForm调用其自身的Close()方法。在项目的MainForm上调用Close()总是终止应用程序,因为这是在TCustomForm.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 // <-- HERE
        else if CloseAction = caHide then Hide
        else if CloseAction = caMinimize then WindowState := wsMinimized
        else Release;
    end;
end;

只有次级 TForm 对象才会遵守 OnClose 处理程序的输出。

要做你所要求的事情,你可以选择以下方法之一:

  • 直接处理 WM_CLOSE 并跳过 Close()

  • private
      procedure WMClose(var Message: TMessage); message WM_CLOSE;
    
    procedure TForm1.WMClose(var Message: TMessage);
    begin
      Hide;
      // DO NOT call inherited ...
    end;
    
  • 让您的主窗体的OnClose处理程序直接调用Hide(),并返回caNone

  • procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      Hide;
      Action := caNone;
    end;
    

8
尝试使用OnCloseQuery事件。隐藏窗体并将CanClose设置为False。这样做应该可以了。
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  Hide;
  CanClose := False;
end;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接