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);
How to hide firemonkey application button from Taskbar (XE4)?
-
30-05-2022 - |
質問
According to this question it is possible to hide fmx taskbar icon by changing window style to WS_EX_TOOLWINDOW. In XE2 and XE3 this code works:
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;
In XE4 this solution does not work (application button should become hidden but nothing happens). any body have any idea?
Thanks.
解決 4
他のヒント
Just tried this in XE7 and of course it didn't work. However a little look into FMX.PlatformWin shows the application handle is now exposed through the ApplicationHWND function, so the code that works on XE7 (don't forget to include unit FMX.Platform.Win
and Winapi.Windows
) is...
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;
The ShowWindow at the end is optional - it seems to make no difference. You can remove the extended styles and restore the WS_EX_APPWINDOW style to show the toolbar icon again.
It seems that in XE4 FM apps there is no more handle for the application object. So we need to get the parent of the main form. Below two small methods to hide/show your app on the taskbar.
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;
We could also have used "Application.MainForm" instead of passing the mainform, but this variable is not assigned during the "OnCreate" Event of the mainform.
So in your "OnCreate" Event off your mainform you can simply write:
procedure TMyMainForm.FormCreate(Sender: TObject);
begin
HideAppOnTaskbar (self);
end;
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;
This is for Delphi 10.3, it might work in other versions too.
I don't know if you noticed, but whenever your code reachs FormCreate procedure, your FMX application will already have created a taskbar button, at least on Delphi 10.3.3 Rio, which is something we might not like. So if you use the suggested methods your application will fastly show its icon in the taskbar just to hide it.
So if you have access to Delphi's VCL/FMX source code files, and you don't like to show your application taskbar icon not even for a millisecond, you just have to modify FMX.Platform.Win.pas
file located at c:\Program Files (x86)\Embarcadero\Studio\20.0\source\fmx\
directory, then copy it to your projects directory, so it will be picked instead of the original one, and modify the CreateAppHandle
function as suggested below:
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;
That's it, you won't need the other methods, notice it also has CreateWindowEx
passing the styles for your window, if you want to hide it from Alt-Tab list too, replace WS_EX_APPWINDOW
with WS_EX_TOOLWINDOW
instead.