Перейти к содержанию
  • Регистрация
  • 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 эмодзи.

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

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

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


  • Похожий контент

    • От Данил Абдрафиков
      В Color Constants есть константа clActiveCaption, которая возвращает цвет активного окна, но в Windows 10 возвращается совсем не тот цвет, который на данный момент.
      Пробовал так:
      GetSysColor(COLOR_ACTIVECAPTION) Или:
      clActiveCaption В общем-то есть предположение, что это давно уже не работает и несовместимо с Windows 8/10. Есть костыли по вытаскиванию цвета активного окна?
    • От Pulsarius
      Здравствуйте!
      Может кто-нибудь уже проходил через подобное и знает как это реализовать и подскажет. Мне нужно программно создать виртуальный модем и входящее подключение через него. Ну или хотя бы через командную строку. Пробовал через RAS API, но получается не то, что мне нужно. Вот визуализация того, что мне нужно проделать:
       
    • От DirtyBorov
      Подскажите как можно изменить иконку окна в runtime? 
      Суть проблемы в том, что мне надо поддерживать приложение для разных заказчиков. Каждый из них хочет иметь собственную иконку в приложении. Очевидное решение - создать несколько проектов и каждому задать требуемую иконку. Однако на практике это весьма утомительное занятие. Хотелось бы сделать одно приложение, а иконки подгружать динамически на основании настроек приложения.
      Вспоминая практику VCL и WinAPI, подменить иконку Application оказалось задачей тривиальной:
      NewAppIcon := TIcon.Create; NewAppIcon.LoadFromFile(AIconFile); SendMessage(ApplicationHWND, WM_SETICON, 1, NewAppIcon.Handle); А вот дальше начались проблемы. Окна уже прогрузили иконку по умолчанию и добраться до них у меня не получается. 
      Добраться через стиль не получается, потому что TForm не является наследником TStyledObject и не имеет StylesData. Через FindStyleResource тоже не получается добраться.
       
      Может кто знает как?
       
    • От vladimi-r
      Существуют ли готовые решения для Win и Mac?
  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

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