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

Нарисовать TСontrol без вывода на экран


Maka

Вопрос

Ситуация такая. Я хочу отобразит некий фрейм с кучей компонентов с использованием плавного проявления (анимация свойства Opacity)

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

Выход: Сделать скриншот фрейма, плавно и красиво его показать, потом скрыть и на его место поместить целевой фрейм.

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

Пробовал делать MakeScreenshot в событии onPaint фрейма, и там же его скрыть сразу. Действует, но периодически получается моргание, из-за того, что фрейм все же на долю секунды появляется на экране.

Пробовал делать Repaint рекурсивно для фрейма и всех дочерних элементов перед снятием скриншота:

  procedure Repchild(aCtr: TControl);
  var
    xA: SmallInt;
  begin
    aCtr.Repaint;
    for xA := 0 to aCtr.ChildrenCount - 1 do if aCtr.Children[xA] is TControl then Repchild(Tcontrol(aCtr.Children[xA]));    
  end;

без результатно.

Подскажите, как отрисовать TContro без вывода на экран?

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

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

  • 0

Хороший вопрос. Отрисовка в FMX это весьма хитрая штука.

Как вариант (кривой если честно, тем не менее) - отображайте TControl вне границ экрана, тогда и MakeScreenshot корректно отработает, и мерцать на экране не будет.

Ссылка на комментарий
  • 0
2 минуты назад, #WAMACO сказал:

и еще костыль.... подготовьте заранее картинку экрана...ее и проявляйте медленно...

так и делаю, и вопрос в том и заключается, как ее правильно заранее подготовить

Изменено пользователем Maka
Ссылка на комментарий
  • 0
8 минут назад, Maka сказал:

так и делаю, и вопрос в том и заключается, как ее правильно заранее подготовить

ну так первый раз вывести "честно", снять скриншот, записать в ресурсы, распространять вместе с программой и данный скрин и проявлять медленно...

Ссылка на комментарий
  • 0
59 минут назад, Tumaso сказал:

Как вариант (кривой если честно, тем не менее) - отображайте TControl вне границ экрана, тогда и MakeScreenshot корректно отработает, и мерцать на экране не будет.

Возможно так и придется поступить

39 минут назад, #WAMACO сказал:

ну так первый раз вывести "честно", снять скриншот, записать в ресурсы, распространять вместе с программой и данный скрин и проявлять медленно...

Нет, не пойдет, т.к. содержимое выводимых контролов постоянно меняется, и будет чехорда из "красивых" и "некрасивых" вариантов вывода

 

40 минут назад, dnekrasov сказал:

А чем PaintTo не устраивает?

Вот, видоизменил код Ярослава Бровина для сохранения скриншота:

procedure ActionMakeScreenshotExecute(aCtr: TControl);
  var
    BitmapBuffer: TBitmap;
    SourceRect: TRectF;
  begin
    aCtr.Visible := True;
    aCtr.BringToFront;
    aCtr.Opacity := 1;
    // Фиксируем размер снимаемой области
    SourceRect := TRectF.Create(0, 0, aCtr.Width, aCtr.Height);
    // Создаем временный буфер для получения скриншота
    BitmapBuffer := TBitmap.Create(Round(SourceRect.Width), Round(SourceRect.Height));
    try
      // Переводим канву в режим отрисовки - начинаем процесс отрисовки сцены
      if BitmapBuffer.Canvas.BeginScene then
        try
          // Говорим контролу отрисовать себя в канве нашего буфера в указанной области
          aCtr.PaintTo(BitmapBuffer.Canvas, SourceRect);
        finally
          // Завершаем процесс отрисовки, заканчивая формируемую сцену
          BitmapBuffer.Canvas.EndScene;
        end;
      BitmapBuffer.SaveToFile(DateDir + 'screenshot1.png');
    finally
      FreeAndNil(BitmapBuffer);
    end;
  end;

И если мы сюда отправим еще не отрисованный контрол, то получим пустой скриншот, а последующие вызовы будут сохранять не текущее, а последнее нарисованное состояние контрола.

Или есть другой способ воспользоваться PaintTo?

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

Как вариант (кривой если честно, тем не менее) - отображайте TControl вне границ экрана, тогда и MakeScreenshot корректно отработает, и мерцать на экране не будет.

По поводу корректности MakeScreenshot в данном сценарии  - это предположение, или личный опыт?

У меня получается так:

Отображаю нужный контрол за пределами экрана, отлавливаю OnPaint контрола, и в нем делаю MakeScreenshot.

В результате какие-то элементы попадают на скриншот (например TCharts, TRectangle, ), а какие-то нет (например кнопки, эдиты).  Эффект тени от кнопки попадает, а сама кнопка нет..  И прочие чудеса.

 

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

Быть может это натолкнет более опытных товарищей на какую-нибудь идею, решающую проблему:

Удалось понять, что на скриншот не попадают элементы, для которых доступна работа со стилями, и прекрасно перерисовываются элементы без стилей (Effects, Shapes)

 

Изменено пользователем Maka
Ссылка на комментарий
  • 0
16 минут назад, Maka сказал:

на скриншот не попадают элементы, для которых доступна работа со стилями

Попробуйте перед снятием скриншота насильно применять стиль всех для элементов.
Вызывайте для каждого контрола процедуру ApplyStyleLookup();

Изменено пользователем Barbanel
Ссылка на комментарий
  • 0
19 минут назад, Barbanel сказал:

Попробуйте перед снятием скриншота насильно применять стиль всех для элементов.
Вызывайте для каждого контрола процедуру ApplyStyleLookup();

Да, это помогло. Спасибо!

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

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

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

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

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

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

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

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

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

  • Последние посетители   0 пользователей онлайн

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