在多表单应用程序中更改 window 顺序

Changing window order in multi-form application

我有一个包含一些非模态表单的应用程序,每个表单都有自己的图标。我需要任务栏上所有表单的图标都不会在 minimize/restore 上消失,经过一些测试,这是我的解决方案。

申请

Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;

TForm1 - 主窗体有一个 TButton

procedure TForm1.btn1Click(Sender: TObject);
begin
  TForm2.Create(Application).Show;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  SetWindowLong(Handle, GWL_EXSTYLE, WS_EX_APPWINDOW);
  Application.OnRestore := FormShow;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  ShowWindow(Application.Handle, SW_HIDE);
end;

TForm2

procedure TForm2.FormCreate(Sender: TObject);
begin
  SetWindowLong(Handle, GWL_EXSTYLE, WS_EX_APPWINDOW);
end;

这将在任务栏上创建 2 个图标,在 Alt + Tab 中创建 2 个 windows,两者都按预期工作,除了一件事...切换应用程序会将所有先前的应用程序 windows 移动到当前应用程序 window 之前,而不仅仅是一个 window.

例如,我的应用程序有主窗体和其他非模态窗体。如果我在 Google Chrome 中并按 Alt + Tab,那么这将应用程序,这很好。

但这会将我所有的应用程序 windows 移动到 Google Chrome 之前和下一个 Alt + Tab 我看到了,所以我必须按 Alt + 2x Tab 返回 Chrome。

我想实现这种行为,就像我有更多的应用程序而不是一个有多个应用程序一样 windows。

我不确定它到底是如何工作的,但我假设后台有多个列表,一个用于所有应用程序,一个用于应用程序的windows,所以当我切换应用程序时,它在列表中移动到前一个之前,因此它的所有 windows.

如果这是它的工作原理,是否可以选择切换应用程序而不仅仅是 windows?如果不是,是否可以更改行为以不移动所有 windows 而只移动一个活动的 window 或者我的整个过程是错误的并且可以通过不同的方式实现相同的效果,它的工作方式应该?

现在我更好地理解了您的问题,问题是 TApplication 也有一个 window 并且在您看到的行为中发挥作用。 解决方案相当简单,确保所有顶级 windows 除了 TApplication 之外都有 WS_EX_APPWINDOW。第二个问题是 TApplication 是这些 windows 的父级,而不是桌面,因此您需要指定它。

表格 1:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
  strict protected
    procedure CreateParams(var Params: TCreateParams); override;
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  Unit2;

{ TForm1 }

procedure TForm1.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
  // make desktop the owner, not the TApplication window
  Params.WndParent := GetDesktopWindow;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 SetWindowLong(Application.Handle, GWL_EXSTYLE,  GetWindowLong(Application.Handle,GWL_EXSTYLE) and not WS_EX_APPWINDOW or WS_EX_TOOLWINDOW);
 Form2 := TForm2.Create(Application);
 Form2.Show;
end;

end.

表格 2:

unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TForm2 = class(TForm)
  strict protected
    procedure CreateParams(var Params: TCreateParams); override;
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

{ TForm2 }

procedure TForm2.CreateParams(var Params: TCreateParams);
begin
  inherited;
  Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
  // make desktop the owner, not the TApplication window
  Params.WndParent := GetDesktopWindow;
end;

end.