代码之家  ›  专栏  ›  技术社区  ›  Yona

如何防止从主窗体显示和/或关闭辅助窗体时焦点丢失?

  •  3
  • Yona  · 技术社区  · 14 年前

    次要表单可以由主表单直接创建,也可以由第二个表单创建第三个表单。

    二级窗体在OnClose事件中设置caFree:

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

    使用Delphi2009(更新3&4)和XP SP3。

    下面是我重现问题的步骤:

    1. 创建新的VCL窗体应用程序
    2. 如上所述分配OnClose事件
    3. 将按钮拖到创建的窗体上
    4. 在click处理程序中创建一个新的TForm1并如下所示

    运行程序。单击按钮以显示第二个窗体。单击第二个窗体上的按钮以创建第三个窗体。当关闭两个新窗体时,主窗体将失去焦点。

    这是按钮单击事件处理程序中的代码:

    with TForm1.Create(Application) do
        show;
    

    有什么方法可以阻止我的主要形式失去焦点?


    在过去我 the same issue 这是通过更新我的delphi安装来解决的,但是在那个场景中,我没有在OnClose事件中使用caFree,这就是为什么 缺陷。

    A recommendation

    4 回复  |  直到 7 年前
        1
  •  3
  •   Sertac Akyuz    13 年前

    我会在其中一个表单关闭之前,通过api调用手动激活“拥有”窗口:

    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      Action := caFree;
      SetForegroundWindow(GetWindowLong(Handle, GWL_HWNDPARENT));
    end;
    

    这不会是操作系统的问题(即没有闪烁的任务栏按钮),因为我们的应用程序已经在前台。

    如果 MainFormOnTaskBar 如果设置为,则拥有的窗口将是我们的主窗体,如果不是,则它将是隐藏的应用程序窗口。无论哪种情况,应用程序都将保持在前台。

    这个 SetForegroundWindow MainFormOnTaskBar公司 是真的,从那时起,主窗体将不会被拥有,但我不会太在意它(然后,一个人当然可以在调用它之前包含一个测试)。。

        2
  •  1
  •   Marjan Venema    14 年前

    为了防止主窗体失去焦点,您需要注释掉

    // Application.MainFormOnTaskBar := True;
    

    但是,这也可以确保在关闭从辅助窗体创建的窗体时,将关闭从辅助窗体创建的窗体。例如:

    • 主窗体创建第二个1

    关闭Secondary1也将关闭Secondary2和Secondary3。

    如果这是不需要的行为,可以通过显式设置PopupParent来声明更多的控制。例如,将所有表单“父”到应用程序的主表单:

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      PopupMode := pmAuto;
      if Self <> Application.MainForm then
        PopupParent := Application.MainForm;
    end;
    

    这样可以确保Application.MainForm将保留在所有其他窗体之后;所有其他窗体都可以切换到前台;当主窗体关闭时,所有窗体都将关闭。

        3
  •  0
  •   Yona    14 年前

    一个快速而肮脏的解决方案是在项目源中注释MainFormOnTaskbar行:

    program Project1;
    
    uses
      Forms,
      Unit1 in 'Unit1.pas' {Form1};
    
    {$R *.res}
    
    begin
      Application.Initialize;
    //  Application.MainFormOnTaskbar := True;
      Application.CreateForm(TForm1, Form1);
      Application.Run;
    end.
    

    更新

    如果希望主窗体始终位于其他窗体之后,则还应重写CreateParams。以下代码按您的预期工作,但我怀疑它可能因其他原因而无法使用:

    type
      TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
      protected
        procedure CreateParams(var Params: TCreateParams); override;
      public
        { Public declarations }
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.dfm}
    
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      with TForm1.Create(Application) do
        show;
    end;
    
    procedure TForm1.CreateParams(var Params: TCreateParams);
    begin
      inherited CreateParams(Params);
      if Application.MainForm <> nil
        then Params.WndParent:= Application.MainForm.Handle
        else Params.WndParent:= 0;
    end;
    
    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      Action := caFree;
    end;
    
    end.
    
        4
  •  0
  •   Tristan Marlow    11 年前

    修复: 自我,隐藏 在OnClose事件中。

    procedure TPopupForm.FormClose(Sender: TObject;
      var Action: TCloseAction);
    begin
      Self.Hide;
      Action := caFree;
    end;