您应该设置
Application.MainFormOnTaskBar := True
在您的.dpr文件中设置并永远不要修改该设置。
然后,当您想从任务栏中删除主窗体时,只需编写
MainForm.Hide
当您需要再次显示主表单时,请编写以下代码:
MainForm.Show;
就是这样。
当你展示和隐藏主窗体时,自然会想要同时显示和隐藏通知区域图标。
HideWindowFromTaskbar
中的代码不是必需的,你应该将其删除。当你的应用程序处于 MainFormOnTaskBar
等于 True
模式时,主窗体是一个未拥有的顶级窗口。因此,只要它可见,它就会出现在任务栏上。所以,你可以通过隐藏主窗体来将其从任务栏中移除。
你的应用程序中的其他窗体将是拥有者顶级窗口。通常情况下,它们将由你的主窗体拥有。作为所有者,它们将不会出现在任务栏中。
总的来说,你应该尽量避免调整窗口样式。通常情况下,你可以使应用程序按照你需要的方式运行而无需这样做。更重要的是,如果你必须调整窗口样式,你必须在 CreateParams
中进行。这样窗口样式将在窗口重新创建时保持不变。但我再次重申,尽可能避免修改窗口样式。
关键的 MSDN 参考资料有:
这是我能够证明这一点的最小程序:
program MainFormHiding;
uses
Forms, StdCtrls;
var
MainForm, OtherForm: TForm;
Button: TButton;
type
TEventHandlerClass = class
class procedure ToggleMainFormVisible(Sender: TObject);
end;
class procedure TEventHandlerClass.ToggleMainFormVisible(Sender: TObject);
begin
MainForm.Visible := not MainForm.Visible;
end;
begin
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm, MainForm);
OtherForm := TForm.Create(Application);
MainForm.Caption := 'Main Form';
OtherForm.Visible := True;
OtherForm.Caption := 'Other Form';
Button := TButton.Create(OtherForm);
Button.Caption := 'Toggle';
Button.Parent := OtherForm;
Button.OnClick := TEventHandlerClass.ToggleMainFormVisible;
Application.Run;
end.
在您的评论中,您明确表示希望能够隐藏任务栏窗口而不隐藏主窗体。在这种情况下,我建议您将 MainFormOnTaskbar
设置为 False
。这意味着 Application.Handle
将是与任务栏按钮关联的窗口。然后,您可以隐藏该窗口以将其从任务栏中删除。
现在,您需要显式设置 PopupParent
以供任何辅助窗体使用。如果您希望这些窗口归主窗体所有,则可以进行设置。
这是适用于此场景的示例:
program MainFormHiding;
uses
Forms, StdCtrls, Windows;
var
MainForm, OtherForm: TForm;
Button: TButton;
type
TEventHandlerClass = class
class procedure ToggleTaskbarButton(Sender: TObject);
end;
class procedure TEventHandlerClass.ToggleTaskbarButton(Sender: TObject);
begin
if IsWindowVisible(Application.Handle) then
ShowWindow(Application.Handle, SW_HIDE)
else
ShowWindow(Application.Handle, SW_SHOW);
end;
begin
Application.MainFormOnTaskbar := False;
Application.CreateForm(TForm, MainForm);
OtherForm := TForm.Create(Application);
OtherForm.PopupParent := MainForm;
MainForm.Caption := 'Main Form';
Application.Title := MainForm.Caption;
OtherForm.Visible := True;
OtherForm.Caption := 'Other Form';
Button := TButton.Create(OtherForm);
Button.Caption := 'Toggle';
Button.Parent := OtherForm;
Button.OnClick := TEventHandlerClass.ToggleTaskbarButton;
Application.Run;
end.
运行此程序并单击切换按钮。现在您将看到主窗体和其他窗体正在显示。任务栏上没有任何内容。我加入了切换按钮以显示您可以在程序运行时在两种操作模式之间切换。无需重新启动它。
关键是使除可见窗体之外的窗口成为与任务栏相关联的窗口。一旦这样做,您就可以通过显示和隐藏该窗口来再次控制任务栏的存在。在这种情况下,该窗口是应用程序窗口。因为那是任务栏上的窗口,所以您需要设置其
Title
属性以控制其文本。
最后,请再次强调,与任务栏的交互最好使用窗口所有者和可见性进行控制。始终使用这些方法寻找解决方案,而不是
ITaskbarList
、扩展窗口样式等。
更新
希望这是这个主题的最后几句话。正如您已经注意到的,上面直接的代码在将主窗体最小化时具有较差的行为。当发生这种情况时,应用程序窗口再次变为可见状态,因此再次显示在任务栏中。
当涉及到抑制此行为时,我自己并不太确定。这种行为是由
TApplication.Minimize
中的代码引起的,当主窗体最小化时,它会显示应用程序句柄。我最好的解决方案是将主窗体的最小化转换为隐藏。
procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
....
procedure TMainForm.WMSysCommand(var Msg: TWMSysCommand);
begin
if (Msg.CmdType and $FFF0)=SC_MINIMIZE then
begin
Hide;
exit;
end;
inherited;
end;
另一种方法是通过
TApplication
的
OnMinimize
事件处理程序来抑制应用程序窗口显示。
class procedure TEventHandlerClass.ApplicationMinimize(Sender: TObject);
begin
ShowWindow(Application.Handle, SW_HIDE);
end;