如何从任务栏(XE4)隐藏firemonkey应用程序按钮?

时间:2013-05-27 08:17:25

标签: windows delphi delphi-xe3 firemonkey-fm2 delphi-xe4

根据此question,可以通过将窗口样式更改为 WS_EX_TOOLWINDOW 来隐藏fmx任务栏图标。 在XE2和XE3中,此代码有效:

uses FMX.Platform.Win, Winapi.Windows;

procedure TForm1.Button1Click(Sender: TObject);
var h:THandle;
begin
  h := FmxHandleToHWND(Handle);
  ShowWindow(h, SW_HIDE);
  SetWindowLong(h, GWL_EXSTYLE, GetWindowLong(h, GWL_EXSTYLE) or WS_EX_TOOLWINDOW);
  ShowWindow(h, SW_SHOW);
end;

在XE4中,此解决方案不起作用(应用程序按钮应该隐藏但没有任何反应)。任何人都有任何想法吗?

感谢。

5 个答案:

答案 0 :(得分:3)

在XE7中试过这个,当然它没有用。然而,稍微了解FMX.PlatformWin显示应用程序句柄现在通过ApplicationHWND函数公开,因此适用于XE7的代码(不要忘记包含单元FMX.Platform.WinWinapi.Windows)是...

procedure HideAppOnTaskbar (AMainForm : TForm);
var
  AppHandle : HWND;
begin
  AppHandle := ApplicationHWND; 
  ShowWindow(AppHandle, SW_HIDE);
  SetWindowLong(AppHandle, GWL_EXSTYLE, GetWindowLong(AppHandle, GWL_EXSTYLE) and (not     WS_EX_APPWINDOW) or WS_EX_TOOLWINDOW);
  //ShowWindow(AppHandle, SW_SHOW);
end;

最后的ShowWindow是可选的 - 似乎没什么区别。您可以删除扩展样式并恢复WS_EX_APPWINDOW样式以再次显示工具栏图标。

答案 1 :(得分:2)

似乎在XE4 FM应用程序中没有应用程序对象的句柄。 所以我们需要获取主窗体的父级。 以下两种小方法可以在任务栏上隐藏/显示您的应用。

procedure HideAppOnTaskbar (AMainForm : TForm);
var
  AppHandle : HWND;
begin
  AppHandle := GetParent(FmxHandleToHWND(AMainForm.Handle));
  ShowWindow(AppHandle, SW_HIDE);
  SetWindowLong(AppHandle, GWL_EXSTYLE, GetWindowLong(AppHandle, GWL_EXSTYLE) or WS_EX_TOOLWINDOW);
end;

procedure ShowAppOnTaskbar (AMainForm : TForm);
var
  AppHandle : HWND;
begin
  AppHandle := GetParent(FmxHandleToHWND(AMainForm.Handle));
  ShowWindow(AppHandle, SW_HIDE);
  SetWindowLong(AppHandle, GWL_EXSTYLE, GetWindowLong(AppHandle, GWL_EXSTYLE) and (not WS_EX_TOOLWINDOW));
  ShowWindow(AppHandle, SW_SHOW);
end;

我们也可以使用“Application.MainForm”而不是传递mainform,但是在mainform的“OnCreate”事件期间没有分配这个变量。

因此,在您的主要形式的“OnCreate”事件中,您只需写下:

procedure TMyMainForm.FormCreate(Sender: TObject);
begin
  HideAppOnTaskbar (self);
end;

答案 2 :(得分:0)

HWND hWnd = NULL;
DWORD pid, current_pid = GetCurrentProcessId();
do 
{
    hWnd = FindWindowExA(NULL, hWnd, "TFMAppClass", NULL);
    if(hWnd)
    {
        GetWindowThreadProcessId(hWnd, &pid);
        if(current_pid == pid)
            break;
    }
} while(hWnd);

::SetParent(FmxHandleToHWND(Handle), NULL);
::ShowWindow(hWnd, SW_HIDE);

答案 3 :(得分:0)

procedure HideAppOnTaskbar;
var
  appHandle: HWND;
  pid, current_pid: DWORD;
  name: String;

begin
  //ShowWindow(FindWindowA('TFMAppClass', nil), SW_HIDE);

  name := ChangeFileExt(ExtractFileName(ParamStr(0)), '');

  appHandle := 0;
  pid := 0;
  current_pid := GetCurrentProcessId();
  repeat
  begin
    //appHandle := FindWindowExA(0, appHandle, 'TFMAppClass', nil);
    appHandle := FindWindowExA(0, appHandle, 'TFMAppClass', PAnsiChar(AnsiString(name)));
    if (appHandle>0) then
    begin
      GetWindowThreadProcessId(appHandle, pid);
      if (current_pid = pid) then break;
    end;
  end
  until (appHandle>0);

  //SetParent(FmxHandleToHWND(Handle), nil);
  ShowWindow(appHandle, SW_HIDE);

end;

答案 4 :(得分:0)

这适用于 Delphi 10.3,它可能也适用于其他版本。

我不知道您是否注意到,但是每当您的代码到达 FormCreate 过程时,您的 FMX 应用程序就已经创建了一个任务栏按钮,至少在 Delphi 10.3.3 Rio 上是这样的我们可能不喜欢。因此,如果您使用建议的方法,您的应用程序将在任务栏中快速显示其图标以隐藏它。

因此,如果您可以访问 Delphi 的 VCL/FMX 源代码文件,并且您不希望显示您的应用程序任务栏图标甚至一毫秒,您只需修改位于 {{ 1}} 目录,然后将其复制到您的项目目录,因此它将被选中而不是原始目录,并按照以下建议修改 FMX.Platform.Win.pas 函数:

c:\Program Files (x86)\Embarcadero\Studio\20.0\source\fmx\

就是这样,你不需要其他方法,注意它还有 CreateAppHandle 传递你窗口的样式,如果你也想从 Alt-Tab 列表中隐藏它,替换 function TPlatformWin.CreateAppHandle: HWND; var ... begin ... Result := CreateWindowEx(WS_EX_WINDOWEDGE or WS_EX_APPWINDOW, FMAppClass.lpszClassName, PChar(FTitle), WS_POPUP or WS_GROUP, 0, 0, 0, 0, GetDesktopWindow, 0, hInstance, nil); if FApplicationHWND = 0 then // modified/added line Winapi.Windows.ShowWindow(Result, SW_HIDE) // modified/added line else // modified/added line Winapi.Windows.ShowWindow(Result, SW_SHOWNORMAL); end; CreateWindowEx 代替。