在多表单应用程序中更改 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.
我有一个包含一些非模态表单的应用程序,每个表单都有自己的图标。我需要任务栏上所有表单的图标都不会在 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.