При разработке приложений с несколькими формами в Delphi FMX разработчики часто сталкиваются с проблемой управления окнами через кнопки таскбара. В отличие от VCL, FMX не предоставляет встроенных механизмов для работы с отдельными кнопками таскбара для каждой формы.
Основная проблема, описанная в обсуждении, заключается в следующем: - При создании нескольких форм с отдельными кнопками на таскбаре - При клике на кнопку таскбара главной формы, активной остается дочерняя форма - Невозможно определить, какая именно кнопка таскбара была нажата
Решение с использованием подклассирования окон
Один из подходов к решению этой проблемы - использование подклассирования окон (window subclassing). Этот метод позволяет перехватывать сообщения Windows до их обработки FMX.
type
TMainForm = class(TForm)
procedure FormCreate(Sender: TObject);
private
{$IFDEF MSWINDOWS}
procedure CreateHandle; override;
{$ENDIF}
end;
{$IFDEF MSWINDOWS}
uses
Winapi.Windows, Winapi.Messages, Winapi.CommCtrl, FMX.Platform.Win;
function SubclassProc(Wnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM;
uIdSubclass: UINT_PTR; dwRefData: DWORD_PTR): LRESULT; stdcall;
begin
case uMsg of
WM_NCDESTROY:
begin
RemoveWindowSubclass(Wnd, SubclassProc, uIdSubclass);
end;
WM_ACTIVATE:
begin
if wParam in [WA_ACTIVE, WA_CLICKACTIVE] then
begin
SetFocus(Wnd);
end;
end;
end;
Result := DefSubclassProc(Wnd, uMsg, wParam, lParam);
end;
procedure TMainForm.CreateHandle;
var
Wnd: HWND;
ExStyle: LONG_PTR;
begin
inherited;
Wnd := FormToHWND(Self);
ExStyle := GetWindowLongPtr(Wnd, GWL_EXSTYLE);
SetWindowLongPtr(Wnd, GWL_EXSTYLE, ExStyle or WS_EX_APPWINDOW);
SetWindowSubclass(Wnd, SubclassProc, 1, DWORD_PTR(Self));
end;
{$ENDIF}
procedure TMainForm.FormCreate(Sender: TObject);
begin
{$IFDEF MSWINDOWS}
var icc: TInitCommonControlsEx;
icc.dwSize := SizeOf(icc);
icc.dwICC := ICC_INTERNET_CLASSES or ICC_USEREX_CLASSES or ICC_DATE_CLASSES;
InitCommonControlsEx(icc);
{$ENDIF}
end;
Если подклассирование не дает желаемого результата, можно попробовать альтернативный подход - скрыть стандартную кнопку таскбара приложения и создать отдельные кнопки для каждой формы:
procedure TMainForm.FormCreate(Sender: TObject);
{$IFDEF MSWINDOWS}
var
Wnd: HWND;
ExStyle: LONG_PTR;
{$ENDIF}
begin
{$IFDEF MSWINDOWS}
Wnd := ApplicationHWND;
ExStyle := GetWindowLongPtr(Wnd, GWL_EXSTYLE);
SetWindowLongPtr(Wnd, GWL_EXSTYLE, (ExStyle and (not WS_EX_APPWINDOW)) or WS_EX_TOOLWINDOW);
{$ENDIF}
end;
Для дочерних форм:
procedure TChildForm.CreateHandle;
var
Wnd: HWND;
ExStyle: LONG_PTR;
begin
inherited;
Wnd := FormToHWND(Self);
ExStyle := GetWindowLongPtr(Wnd, GWL_EXSTYLE);
SetWindowLongPtr(Wnd, GWL_EXSTYLE, ExStyle or WS_EX_APPWINDOW);
end;
Проблемы и ограничения
Минимизация окон: При использовании альтернативного подхода минимизация главной формы может привести к скрытию всех кнопок таскбара.
Мигание главной формы: При попытке скрыть главную форму и использовать дочернюю как основную, главная форма может кратковременно появляться при запуске.
Сложность определения нажатой кнопки: Прямое определение, какая именно кнопка таскбара была нажата, остается сложной задачей в FMX.
Рекомендации
Использование стандартного поведения: В большинстве случаев лучше использовать стандартное поведение FMX с одной кнопкой таскбара.
ITaskbarList интерфейс: Для более сложных сценариев можно рассмотреть использование Windows API ITaskbarList для управления кнопками таскбара.
Переход на VCL: Если управление окнами критически важно для приложения, стоит рассмотреть переход на VCL, который предоставляет больше возможностей для работы с окнами Windows.
Заключение
Работа с кнопками таскбара в FMX приложениях требует глубокого понимания Windows API и особенностей платформы FMX. Представленные решения могут помочь в реализации требуемого поведения, но следует учитывать их ограничения и возможные побочные эффекты. В большинстве случаев стандартное поведение FMX является предпочтительным, так как обеспечивает согласованность пользовательского интерфейса в Windows.
Проблема управления окнами через таскбар в FMX и возможные решения, включая подклассирование окон и скрытие стандартной кнопки таскбара.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.