Поддержка Delphi Аэро Стекла и свойства DoubleBuffered - что продолжается и как мы используем их?

Я смущен Delphi 2009/2010 поддержка функций Aero Theme Glass в Windows, и тем, что, точно средства DoubleBuffered, и что это имеет отношение к Аэро стеклу. Я нашел, что DoubleBuffered не является только свойством в VCL, это также найдено в .net WinForms. Первоначально я задался вопросом, установило ли это некоторый бит стиля окна, используемый библиотекой общего контроля, или что. Почему это используется, и когда это должно использоваться?

[Обновление: Я должен заявить, что знаю, какова "двойная буферизация", как общая техника для сокращения мерцания, что я задался вопросом, почему это имеет какое-либо отношение к рендерингу средств управления на области Aero Glass в Windows Vista / Windows 7, и в особенности почему был бы, КНОПКА всех вещей должна иметь верный набор двойной буферизации, для работы по стеклу?. Сообщение в блоге, связанное ниже, кажется самым информативным.]

В частности, я смущен свойством DoubleBuffered, и я хочу знать, почему оно существует, и что его отношения между стеклянной поддержкой и свойством с двойной буферизацией в форме и управлении установлены. При чтении статей C++ как этот, Вы видите, что нет никакого упоминания о двойной буферизации.

[Update2: следующее содержало некоторые фактические ошибки и было исправлено:]

Я нашел некоторых разработчиков C++, говорящих о том, как они могут назвать SetLayeredWindowAttributes, чтобы избежать, чтобы "черный цвет стал стеклянным" незначительным сбоем, что DWM/Aero, составляющие композит причины при включении его в классическом приложении Win32 [однако ссылка ниже блога, говорят мне, что это больше не работает в Windows 7 и на самом деле только кратко работало в Vista до Microsoft, заблокировал его]. [Начните НЕВЕРНОЕ ПРЕДСТАВЛЕНИЕ] Разве, мы не должны использовать некоторый другой цвет, как яркий пурпурный и делать, которые превращаются в стеклянный прозрачный цвет? [Закончите НЕВЕРНОЕ ПРЕДСТАВЛЕНИЕ]

Каковы правила для того, когда DoubleBuffered должен быть установлен и не установлен, и почему DoubleBuffered был добавлен к VCL во-первых? Когда это вызовет проблемы, когда установлено? (Кажется, что удаленный рабочий стол является одним случаем, но это - единственный случай?) и когда это не установлено, мы даны незначительный сбой, представив текста кнопки, скорее всего, потому что кажется, что Delphi не изменяет "рендеринг по умолчанию, черный как стекло" в Аэро DWM.

Мне кажется, что Аэро Стеклянный рендеринг делается существенно в нечетном или твердом для понимания пути [под самим Windows, не под Delphi, который просто переносит эту функциональность], и что много внутреннего исходного кода VCL в 2009/2010 в классах в StdCtrls должно сделать много сложной логики для рендеринга материала правильно на Аэро Стекле, и все же это все еще получило много проблем и смотрит на меня как, он сделал неправильно, и что это могло бы быть позади этого связанного вопроса и проблемы королевского адвоката. [Update3: Большой рендеринг незначительных сбоев на стекле, в VCL представляет сделанный неправильно в общем контроле, которым это кажется, Microsoft не заботится о фиксации. Короче говоря, Delphi, меры кода VCL не могут зафиксировать то, что древней библиотеке стандартных элементов управления Windows и современному [но изворотливый] Аэро Стеклянная функция составления композита не нравится друг друг очень и особенно не работать хорошо вместе. Спасибо Microsoft для создания такой высококачественной технологии и развязывания его на мире.]

И если это еще не была достаточно забава; Почему у нас есть ParentDoubleBuffered?

[Обновление 30 июля: Этот вопрос интересен мне, потому что я думаю, что он показывает, что работа над Windows API для решения этой проблемы, когда у Вас есть большая существующая платформа VCL, является трудной тяжелой проблемой.]

25
задан Community 23 May 2017 в 11:46
поделиться

4 ответа

О DoubleBuffer

.NET может иметь его, и он может иметь то же имя и то же назначение, что и Delphi, но Delphi реализует DoubleBuffer с нуля, и я предполагаю, что .NET делает то же самое. При его реализации не используются биты оконного стиля.

DoubleBuffer и Glass Aero

Довольно просто: Не устанавливайте DoubleBuffer для элементов управления, которые находятся на Glass. Для работы DoubleBuffering необходимо иметь возможность инициализировать "буфер" - но чем его инициализировать для Glass? DoubleBuffering не требуется для стандартных элементов управления Windows (включая TButton). Для новых элементов управления, которым нужны и прозрачные поверхности, и поведение, подобное двойному буферу, можно использовать апи Layered windows.

Получение элементов управления для работы на Glass

Шаг 1:

TForm1 = class(TForm)
...
protected
  procedure CreateWindowHandle(const Params: TCreateParams); override;
...
end;

procedure TForm15.CreateWindowHandle(const Params: TCreateParams);
begin
  inherited;
  SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYERED);
  SetLayeredWindowAttributes(Handle, RGB(60, 60, 60), 0, LWA_COLORKEY);
end;

Шаг 2, это должен быть обработчик OnPaint вашей формы:

procedure TForm15.FormPaint(Sender: TObject);
var rClientRect:TRect;
begin
  if GlassFrame.Enabled then
  begin
    rClientRect := ClientRect;

    Canvas.Brush.Color := RGB(60, 60, 60);
    Canvas.Brush.Style := bsSolid;
    Canvas.FillRect(rClientRect);

    if not GlassFrame.SheetOfGlass then
    begin
      rClientRect.Top := rClientRect.Top + GlassFrame.Top;
      rClientRect.Left := rClientRect.Left + GlassFrame.Left;
      rClientRect.Right := rClientRect.Right - GlassFrame.Right;
      rClientRect.Bottom := rClientRect.Bottom - GlassFrame.Bottom;
      Canvas.Brush.Color := clBtnFace;
      Canvas.FillRect(rClientRect);
    end;
  end;
end;

Шаг 3: Set GlassFrame.Enabled = True; Установите все остальные свойства Glass, добавьте элементы управления на форму, где бы они вам не нравились. Это может быть на Glass или в любом другом месте. Убедитесь, что элементы управления не имеют "DoubleBuffered = True". Вот и все, наслаждайтесь. Я тестировал с TButton, TCkBox и TEdit.

... EDIT ...

К сожалению, при использовании этого метода "Стекло" рассматривается как 100% прозрачная поверхность, а это не так - оно выглядит как стекло, но не ведет себя как стекло. Проблема со 100% прозрачностью заключается в том, что если вы щелкните на этой прозрачной области, ваш щелчок перейдет на окно за вашим окном. Ужасно.

На момент написания этой статьи я уверен, что не существует API для изменения цвета по умолчанию BLACK для оригинального стекла (google находит бесчисленные сообщения в блогах и на форумах о том, что нужно использовать пользовательский рисунок для элементов управления, которые находятся на стекле, и нет функции для изменения этого в списке функций DWM на MSDN). Без изменения цвета по умолчанию BLACK большинство элементов управления не могут корректно отображаться, потому что они пишут текст с помощью clWindowText, а он BLACK. Один из предложенных приемов, найденный на нескольких форумах, заключается в изменении цвета прозрачности с помощью API SetLayeredWindowAttributes. И это работает! После этого черный текст на элементах управления отображается как бросок, но, к сожалению, стекло больше не стекло, стекло выглядит как стекло, но ведет себя как 100% прозрачность. Это практически сводит на нет данное решение и показывает двойные стандарты со стороны Microsoft: Оригинальный BLACK не ведет себя как 100% прозрачность, но если мы изменим его на что-то лучшее, он будет вести себя как 100% прозрачность.

На мой взгляд, распространенное мнение об использовании пользовательских элементов управления на Glass ошибочно. Это единственное, что может сработать, но это неправильно, потому что мы должны использовать элементы управления, согласованные по всей платформе: предложение использовать пользовательские элементы управления открывает дверь для непоследовательных, похожих на winamp приложений, где каждый пользователь переделывает колесо в соответствии со своими художественными идеями. Даже если разработчику удастся точно воссоздать любой элемент управления windows и заставить его работать на стекле, "исправление" будет временным и его придется создавать заново для следующей версии windows. Не говоря уже о том, что необходимо иметь несколько вариантов для существующих версий windows.

Другим решением является использование многослойных окон с UpdateLayeredWindow. Но это неприятно по многим причинам.

Для меня это тупик. Но я поставлю этому вопросу флаг "любимый", если появится что-то лучшее, я хотел бы об этом узнать.

15
ответ дан 28 November 2019 в 21:46
поделиться

DoubleBuffered - это стандартный графический метод , используемый для уменьшения мерцания. По сути, вы рисуете новую версию своей формы на втором холсте, а затем меняете ее на текущую. Этот обмен происходит быстро, даже если процесс рисования идет медленно. Между этим и Aero нет прямой связи - вы можете использовать любой или оба независимо друг от друга. Двойная буферизация существует в Delphi очень-очень давно, но теперь у нас намного больше циклов процессора на обновление экрана, что менее необходимо. Может быть, поэтому вы об этом не слышали.

Двойная буферизация - это то, что вы должны использовать только реактивно - если вы видите мерцание, когда ваше приложение перерисовывает экран, включите его и посмотрите, что произойдет. В этом случае вы в первую очередь обращаетесь к DisableUpdates / EnableUpdates (см. Справку по Delphi) и Windows API LockWindowUpdate (то же самое).

ParentDoubleBuffered, как и большинство Parent ...properties, сообщает вам, будет ли эта форма использовать свойство DoubleBuffered от своего родителя. Это позволяет вам установить свойство один раз в главной форме вашего приложения и повлиять на каждую создаваемую вами форму. Или нет, если вы установите для этого свойства значение false.

Это типичная ситуация, когда у вас есть обратно совместимый код - там есть вещи, которые сегодня редко используются, но все еще работают (а иногда все еще необходимы), хотя большинству людей никогда не нужно о них беспокоиться. Для большинства людей они просто есть, и вы можете их игнорировать, но для некоторых из нас они отчаянно необходимы (у нас есть пара действительно, очень сложных форм, которые мы перерисовываем в иногда сложные шаблоны, чтобы остановить мерцание)

3
ответ дан 28 November 2019 в 21:46
поделиться

Ваш вопрос вызвал сообщение в блоге от CR на Delphi Haven ...

Посмотрев на Stack Overflow, я только что заметил довольно подробный вопрос (действительно, множество вопросов) про Aero стекло.

7
ответ дан 28 November 2019 в 21:46
поделиться

Хорошо, я постараюсь немного поправить ситуацию.

Прежде всего, двойная буферизация - это очень стандартный метод, когда дело доходит до рендеринга на экране. Я использую его постоянно, например, в своем компоненте текстового редактора. Представьте, что текст нужно перерисовать. Проще говоря, я сначала очищаю весь прямоугольник клиента, более или менее с помощью FillRect (ClientRect) , затем рисую линии от первого до последнего видимого, каждая от первого символа до последнего видимого. . Но для конечного пользователя это будет выглядеть очень некрасиво, имея несколько миллисекунд или около того с очищенным дисплеем между двумя состояниями почти с одинаковым текстовым содержимым.

Решение состоит в том, чтобы все рисовать на внеэкранном растровом изображении и просто рисовать внеэкранное растровое изображение на экране, когда оно будет завершено. Затем, если предыдущий и новый кадры идентичны, с дисплеем ничего не произойдет, в отличие от случая без двойной буферизации, когда экран будет отображать пустой белый прямоугольник в течение нескольких миллисекунд, то есть экран будет мерцать. Я всегда использую двойную буферизацию для всех моих визуальных элементов управления, и это действительно значительно улучшает качество и ощущение от них. В современной системе с гигабайтами памяти (RAM) увеличенное использование памяти ни в коем случае не является проблемой. И почти во всех случаях замена буферов происходит более чем достаточно быстро (хотя есть довольно много пикселей для копирования).

Часто можно наблюдать отсутствие двойной буферизации при изменении размеров окон. Иногда они просто мерцают как чёрт.Также может быть интересно заметить, что такие технологии, как OpenGL, изначально имеют двойную буферизацию (по крайней мере, в большинстве случаев).

Таким образом, двойная буферизация не имеет ничего общего с листами стекла. Фактически, большинство потомков Delphi TWinControl имеют свойства DoubleBuffered и ParentDoubleBuffered ( ссылка ).

Свойство ParentDoubleBuffered преобразовано в DoubleBuffered так же, как ParentColor связано с Color , ParentShowHint до ShowHint , ParentFont до Font и т. Д. Он просто решает, должен ли элемент управления наследовать значение параметра от своего родительского окна.

Теперь к вопросу о стекле. Хорошо, общеизвестно, что в общем случае неудобно добавлять элементы управления к листу стекла (или стеклянной раме), по крайней мере, в приложении VCL. Кто-то должен написать длинную статью в блоге , обсуждая, как это сделать правильно ...

1
ответ дан 28 November 2019 в 21:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: