正如David Heffernan已经表示,不可能更改已经运行的应用程序的主窗体。这是窗户本身的限制。
你可以做的就是作弊,永远不会改变主窗体,但只会使它看起来像你一样。
你是如何实现这一目标的?
第1步:将代码添加到第二种形式作出自己的任务栏按钮
procedure TWorkForm.CreateParams(var Params: TCreateParams);
begin
inherited;
Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
end;
第2步:刚切换到它之前动态创建第二种形式。在创建之前添加的代码将为您的第二个表单创建一个新的任务栏按钮。
第3步:现在隐藏您的实际主窗体。隐藏它也会隐藏属于它的任务栏按钮。所以你最终还是会显示一个任务栏按钮,它是属于你的第二个窗体的那个。
步骤4:为了让您的第二个窗体在其闭包调用中终止您的应用程序从您的第二个窗体OnClose或OnFormCloseQuery事件中关闭您的真正主窗体的方法。
如果您想要切换回主窗体的主窗体调用Show方法而不是Close方法。
这种方法允许我们快速交换表单,所以只有最敏锐的用户才会注意到任务栏按钮的短动画。
注意:如果你的第二个是复杂的,并且因为这需要一些时间来创建,你可能会创建它隐藏,然后一旦它的创建过程完成显示它并进行交换。否则,您最终可能会同时显示两个任务栏按钮,我相信您想避免这些按钮。
下面是一个简单的例子:
- LoginForm的是一个真正的主要形式,是在应用程序启动 创造 - 工作表单的是哪个用户会花大部分的时间在登录后的表格,这一次是在登录创建过程
登录表单代码:
unit ULoginForm;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TLoginForm = class(TForm)
BLogIn: TButton;
procedure BLogInClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
LoginForm: TLoginForm;
//Global variable to tell us if we are only logging out or closing our program
LoggingOut: Boolean;
implementation
uses Unit2;
{$R *.dfm}
procedure TLoginForm.BLogInClick(Sender: TObject);
begin
//Create second Form
Application.CreateForm(TWorkForm, WorkForm);
//Hide Main Form
Self.Hide;
//Don't forget to clear login fields
end;
end.
工作表单代码:
unit UWorkForm;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TWorkForm = class(TForm)
BLogOut: TButton;
//Used in overriding forms creating parameters so we can add its own Taskbar button
procedure CreateParams(var Params: TCreateParams); override;
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure BLogOutClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
WorkForm: TWorkForm;
implementation
uses Unit1;
{$R *.dfm}
procedure TWorkForm.BLogOutClick(Sender: TObject);
begin
//Set to true so we know we are in the process of simply logging out
LoggingOut := True;
//Call close method to begin closing the current Form
Close;
end;
procedure TWorkForm.CreateParams(var Params: TCreateParams);
begin
inherited;
Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
end;
procedure TWorkForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
//Check to see if we are in the process of simply logging out
if not LoggingOut then
begin
//If we are not in the process of logging out close the Main Form
LoginForm.Close;
//and then allow closing of current form
CanClose := True;
end
else
begin
//But if we are in the process of simply logging out show the Main Form
LoginForm.Show;
//Reset the LoggingOut to false
LoggingOut := False;
//and then alow closing of current form
CanClose := True;
end;
end;
end.
你可以改变'指针((@ Application.MainForm)^)的主要形式有:=窗体2;'。 – linluk 2014-09-04 15:15:41
@linluk:这是不好的建议。 'MainForm'是一个属性,而不是一个变量。你不能得到一个属性的地址,所以你实际上得到了该属性返回的指针的地址。然后你修改THAT指针指向一个不同的对象,你不会修改TApplication本身内部的指针。 – 2014-09-04 16:28:08
确实听起来很危险:S,它工作到目前为止,我知道这是一个肮脏的黑客攻击,但我会寻找一个更好的解决方案,为我将来的应用程序,我使用它(也许通过rtti设置变量,或者其他)或尝试避免改变主窗体:) – linluk 2014-09-05 06:25:58