Как скрыть кнопку приложения firemonkey с панели задач (XE4)?

В соответствии с этим вопросом можно скрыть значок панели задач fmx, изменив стиль окна на < strong>WS_EX_TOOLWINDOW. В 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 это решение не работает (кнопка приложения должна скрываться, но ничего не происходит). у любого тела есть идеи?

Спасибо.


person mh taqia    schedule 27.05.2013    source источник
comment
у меня это отлично работает на XE3 (без MainformOnTaskbar): использует FMX.Platform.Win ; процедура TForm2.Button1Click(Отправитель: TObject); вар ч:THandle; начало ч := FmxHandleToHWND(Handle); ShowWindow(ч, SW_HIDE); SetWindowLong(h, GWL_EXSTYLE, GetWindowLong(h, GWL_EXSTYLE) или WS_EX_TOOLWINDOW); ShowWindow(ч, SW_SHOW); конец;   -  person bummi    schedule 27.05.2013
comment
MainformOnTaskbar определяет, является ли основная форма свободной. Вероятно, не имеет значения в FMX, где основная форма, вероятно, всегда не принадлежит. Так что использования стиля окна инструмента будет достаточно.   -  person David Heffernan    schedule 27.05.2013
comment
Предлагаемый код не работает на XE4.   -  person mh taqia    schedule 27.05.2013
comment
Ваша цель — предотвратить появление вашего приложения на панели задач вместе (значок + заголовок) или просто удалить значок (видимый заголовок)?   -  person Peter    schedule 27.05.2013
comment
Моя цель - только иконка, название не важно.   -  person mh taqia    schedule 27.05.2013
comment
Вот что я понял, вы должны знать, что вопрос, который вы связали, на самом деле не имеет отношения к этому вопросу, поскольку целью было удалить приложение с панели задач вместе (значок + заголовок)   -  person Peter    schedule 27.05.2013
comment
Ну, я хочу удалить Icon+Title, хорошо?   -  person mh taqia    schedule 27.05.2013
comment
тогда вам следует изменить свой вопрос, чтобы отразить ваш выбор.   -  person Peter    schedule 27.05.2013
comment
Это очень плохо, когда вы говорите, что не работает. Опишите, как именно код дает сбой. Время компиляции? Время выполнения? Не заставляйте нас гадать.   -  person David Heffernan    schedule 27.05.2013
comment
Значок панели задач должен скрываться после нажатия кнопки, но ничего не происходит. Понятно, что приведенный выше код не имеет синтаксических проблем. Я удивлен вашим комментарием.   -  person mh taqia    schedule 27.05.2013
comment
Это не ясно и не работает никогда не бывает достаточно. Будьте откровенны.   -  person David Heffernan    schedule 28.05.2013
comment
Я нашел решение.   -  person mh taqia    schedule 29.05.2013
comment
Можете ли вы поделиться решением, которое вы нашли, пожалуйста? У меня аналогичная проблема со скрытием кнопки панели задач и изменением ее заголовка.   -  person VGeorgiev    schedule 10.12.2013
comment
@VGeorgiev: я поделился запрошенным кодом. Пожалуйста, проголосуйте за вопрос, чтобы свести на нет несправедливое отрицание;)   -  person mh taqia    schedule 10.12.2013


Ответы (4)


Только что попробовал это в XE7, и, конечно, это не сработало. Однако небольшой взгляд на FMX.PlatformWin показывает, что дескриптор приложения теперь доступен через функцию ApplicationHWND, поэтому код, который работает на XE7 (не забудьте включить модуль FMX.Platform.Win и Winapi.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, чтобы значок панели инструментов снова отображался.

person Steve Swallow    schedule 08.10.2014

Кажется, что в приложениях 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» вместо передачи основной формы, но эта переменная не назначается во время события «OnCreate» основной формы.

Итак, в вашем событии «OnCreate» вне вашей основной формы вы можете просто написать:

procedure TMyMainForm.FormCreate(Sender: TObject);
begin
  HideAppOnTaskbar (self);
end;
person Nicki    schedule 05.06.2013
comment
Я протестировал предложенный код. Это не работает (не имеет никакого эффекта). Я думаю, что этот код работает только на XE3; также обратите внимание, что функция FmxHandleToHWND больше не существует в XE4. - person mh taqia; 07.06.2013

Это для Delphi 10.3, может работать и в других версиях.

Я не знаю, заметили ли вы, но всякий раз, когда ваш код достигает процедуры FormCreate, ваше приложение FMX уже создает кнопку на панели задач, по крайней мере, в Delphi 10.3.3 Rio, чего мы могли бы и не делать. как. Поэтому, если вы используете предложенные методы, ваше приложение быстро отобразит свой значок на панели задач, чтобы скрыть его.

Поэтому, если у вас есть доступ к файлам исходного кода Delphi VCL/FMX, и вы не хотите, чтобы значок панели задач вашего приложения отображался даже на миллисекунду, вам просто нужно изменить FMX.Platform.Win.pas файл, расположенный в каталоге c:\Program Files (x86)\Embarcadero\Studio\20.0\source\fmx\, а затем скопировать его в свои проекты. каталог, поэтому он будет выбран вместо исходного, и измените функцию CreateAppHandle, как предлагается ниже:

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, передающий стили для вашего окна, если вы хотите скрыть его и из списка Alt-Tab, вместо этого замените WS_EX_APPWINDOW на WS_EX_TOOLWINDOW.

person vhanla    schedule 25.01.2021

person    schedule
comment
Спасибо. TFMAppClass указал мне правильное направление. Я искал что-то подобное в Spy++, но явно пропустил. - person VGeorgiev; 11.12.2013
comment
Однако есть одна проблема с этим кодом. ShowWindow(FindWindowA("TFMAppClass", NULL), SW_HIDE) скроет первое окно с найденным классом, который может не соответствовать вашему приложению. Что делать, если у вас запущены два приложения Firemonkey или два экземпляра одного... Было бы лучше использовать что-то вроде FindWindow('TFMAppClass', PChar(ChangeFileExt(ExtractFileName(ParamStr(0)), ''))) или еще лучше объединить его с GetWindowThreadProcessId и FindWindowEx, чтобы проверить, принадлежит ли ti вашему процессу. - person VGeorgiev; 11.12.2013
comment
Вы должны использовать EnumWindows() вместо вызова FindWindow() в цикле. - person Remy Lebeau; 13.12.2018