Перейти к содержанию
Fire Monkey от А до Я
  • 0

Тень формы отсутствует при стилизованной границе окна


Алиса Романец

Вопрос

Доброго времени суток, форумчане!

Столкнулась с проблемой при стилизации границ формы окна в FireMonkey на Windows. Как только появляется стиль границ - форма начинает вести себя, как прозрачная - то есть, теряет тень. Кто-то из добрых людей уже замечали эту проблему, но в текущих реалиях прикостылить их решения я не смогла. CreateParams в FMX не существует, а вручную добавлять TShadowEffect в стиль не принесло никаких результатов, кроме съехавшего стиля формы и тормозного изменения размеров. Может ли кто пояснить за этот момент, как вообще тень обрабатывается в MS Windows и есть ли какой-нибудь workaround для её ручной активации через WinAPI? Потому что с тенью в macOS всё прекрасно (однако, там и границу окна не стилизуешь, as long as у вас не веб-приложение, хехе).

Скрины проблемы прикрепила к посту. Стиль полностью векторный.

launchershadow.png

Обновление (19.12.2019 11:44 МСК)

Путём перехвата процедуры CreateHandle и с использованием SetClassLong удалось создать тень, ноо... До тени, что выдаёт Windows 10 ей далеко ?

type
  TForm1 = class(TForm)
private
    {$IFDEF MSWINDOWS}procedure CreateHandle; override;{$ENDIF MSWINDOWS}
public
    { Public declarations }
end;

begin

{$IFDEF MSWINDOWS}
procedure TForm1.CreateHandle;
begin
  inherited CreateHandle;

  var hWnd: HWND := FormToHWND(Form1);
  if hWnd <> 0 then
    SetClassLong(hWnd, GCL_STYLE, GetClassLong(hWnd, GCL_STYLE) or CS_DROPSHADOW);

end;
{$ENDIF MSWINDOWS}

end.

Результат:

Capture89_launcherShadow.png.f2df600d482fedb81dd836ccb793f022.png

Изменено пользователем Алиса Романец
Обновление. Частично решение было найдено самостоятельно.
Ссылка на комментарий

Рекомендуемые сообщения

  • 0
22 минуты назад, Дмитрий Потапов сказал:

Я просто переписал на Delphi это решение (видео на YouTube).
А вот исходник

Решение, написанное ХрисТ'ом: во-первых для VCL (кто-то ранее на форуме уже объяснял, почему в Мартышке нет процедур CreateParams и WndProc), во-вторых - часть его решения уже была переписана вручную (см. обновление к вопросу).

Мне нужно решение именно для FireMonkey, потому и пришла на этот форум.

Ссылка на комментарий
  • 0
1 час назад, Алиса Романец сказал:

Решение, написанное ХрисТ'ом: во-первых для VCL (кто-то ранее на форуме уже объяснял, почему в Мартышке нет процедур CreateParams и WndProc), во-вторых - часть его решения уже была переписана вручную (см. обновление к вопросу).

Мне нужно решение именно для FireMonkey, потому и пришла на этот форум.

CreateParams я не использовал, WndProc тоже (только в одном файле, FMX.Platform.Win вроде).

Есть только одно различие, я не использовал кастомный стиль, использовал пока только Borderless форму и все. Но сегодня попробую еще и с кастомным стилем. 

По итогу получилась Borderless форма с нативной тенью из Windows 10.

Изменено пользователем Дмитрий Потапов
Ссылка на комментарий
  • 0
1 час назад, Дмитрий Потапов сказал:

CreateParams я не использовал, WndProc тоже (только в одном файле, FMX.Platform.Win вроде).

Есть только одно различие, я не использовал кастомный стиль, использовал пока только Borderless форму и все. Но сегодня попробую еще и с кастомным стилем. 

По итогу получилась Borderless форма с нативной тенью из Windows 10.

К моему сожалению, я не такой профессионал Delphi, чтобы полноценно переписать код, что там был. Лучшее, что я смогла сделать - ниже. Однако, тень осталась такой же, как на скрине.

procedure TForm1.CreateHandle;
begin
  inherited CreateHandle;

  var hWnd: HWND := FormToHWND(Self);
  SetClassLong(hWnd, GCL_STYLE, GetClassLong(hWnd, GCL_STYLE) or CS_DROPSHADOW);

  var m: MARGINS;
  m.cxLeftWidth := 0;
  m.cxRightWidth := 0;
  m.cyTopHeight := 0;
  m.cyBottomHeight := 1;

  DwmExtendFrameIntoClientArea(hWnd, m);
end;

 

Изменено пользователем Алиса Романец
Ссылка на комментарий
  • 0
1 час назад, Алиса Романец сказал:

К моему сожалению, я не такой профессионал Delphi, чтобы полноценно переписать код, что там был. Лучшее, что я смогла сделать - ниже. Однако, тень осталась такой же, как на скрине.


procedure TForm1.CreateHandle;
begin
  inherited CreateHandle;

  var hWnd: HWND := FormToHWND(Self);
  SetClassLong(hWnd, GCL_STYLE, GetClassLong(hWnd, GCL_STYLE) or CS_DROPSHADOW);

  var m: MARGINS;
  m.cxLeftWidth := 0;
  m.cxRightWidth := 0;
  m.cyTopHeight := 0;
  m.cyBottomHeight := 1;

  DwmExtendFrameIntoClientArea(hWnd, m);
end;

 

Так и я тоже)

Решение я вообще собирал отчасти по кусочкам с различных форумов. Так же была и ваша часть)

Но, когда я сделал все, у моего окна было "две" тени, одна нативная от Win10, вторая, как у вас. Так что строчка SetClassLong(...) не пригодилась мне, убрав ее я убрал такую тень.

Как буду за домашним пк, то скину сюда пример с кодом.

Ссылка на комментарий
  • 0

В общем. Вот пример.

Для его работоспособности пришлось добавить одну строчку в файл FMX.Platform.Win.pas, связана она с тем, чтобы получить возможность перехватывать сообщения окна. Решение взято было отсюда:

Далее, использовал этот код (написанный на C#). Взяв решение оттуда и просто чуть-чуть переделав его под Delphi смог получить нативную тень над формой. 
 

Проверил на форме с нестандартным стилем (который затрагивает заголовок формы), там есть проблема (не понял, как ее решить, да и не копал особо в эту сторону). Если использовать тень, то заголовок формы перекрывается родным от Windows и из-за этого он полностью ломается (не реагирует на перемещение, изменение размеров и кнопки так же неактивны).

Так что самым простым вариантом с нестандартным стилем для меня оказалось - просто использовать BorderStyle - None, конечно, тогда придется вручную реализовывать бордюр и заголовок, а так же перемещение за заголовок и изменение размеров формы за бордюры.

Но, благо в Firemonkey уже это все реализовано в виде двух простых функций StartWindowDrag и StartWindowResize.

 

В общем, если у кого-то есть идеи, как это можно улучшить и САМОЕ ГЛАВНОЕ решить проблему с нестандартными стилями - буду благодарен за помощь.

BorderlessWindowWithShadow.zip

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...