更改多表单应用程序中的窗口顺序

时间:2017-12-13 15:17:34

标签: windows delphi winapi delphi-10.2-tokyo

我有一个带有一些非模态表单的应用程序,每个表单都有自己的图标。我需要任务栏上所有表单的图标,这些图标在最小化/恢复时不会消失,经过一些测试后,这是我的解决方案。

申请

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个窗口,两者都按预期工作,除了一件事......切换应用程序移动所有以前的应用程序窗口在当前应用程序窗口之前,而不仅仅是一个窗口。

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

enter image description here

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

enter image description here

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

enter image description here

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

如果这是它的工作原理,是否可以选择切换应用程序而不仅仅是窗口?如果没有,是否可以改变行为以不移动所有窗口,但只有一个活动窗口或我的整个过程是错误的,同样的效果可以通过不同的方式实现,它应该在哪里工作?

1 个答案:

答案 0 :(得分:3)

现在我更好地理解了您的问题,问题是TApplication还有一个窗口,并在您看到的行为中发挥作用。 解决方案非常简单,请确保所有顶级窗口都WS_EX_APPWINDOWTApplication之外。第二个问题是TApplication是这些窗口的父级,而不是桌面,所以你需要指定它。

Form1中:

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.