Кнопки Delphi показывают белую границу на Аэро стекле

Я пытался найти красивый дизайн, использующий Аэро в Delphi 2010. Одно из очевидного использования, которое каждый видит, то, где стеклянный кадр расширяется для включения OK/кнопок отмены внизу экрана. Я замечаю, хотя это, это не выглядит совершенно правильным в Delphi 2010 - существует белая граница все вокруг каждой кнопки.

Это изображение показывает проблему: лучшие 3 кнопки из моего приложения, нижняя часть два были взяты от диалогового окна Свойств слоя Paint.NET.

White borders around Delphi controls

Я попробовал различные комбинации DoubleBuffered и несколько комбинаций размещения средств управления на других средствах управления сначала, но проблема остается. Какие-либо идеи?

10
задан Glorfindel 3 August 2019 в 23:06
поделиться

3 ответа

Если ни у кого нет чистого решения, в качестве временного решения используйте TBitBtn с DoubleBuffered = false .

5
ответ дан 4 December 2019 в 02:25
поделиться

Похоже, что единственный обходной путь - это рисование владельцем или стороннее управление кнопками Проверьте стеклянную кнопку Роя Клевер или, как указано в записи QC связанный ниже, TBitBtn с DoubleBuffered = false, который был принятым ответом на этот вопрос выше.

Это ошибка в Windows Aero DWM или ошибка в общих элементах управления Windows, или ошибка в способе, которым иерархия классов VCL обрабатывает общие сообщения окна управления и рисование при рисовании на стекле. Короче говоря, общие элементы управления Windows не рисуют себя должным образом на стекле, или, скорее, нарушена композиция DWM (Aero). Сюрприз Сюрприз.

Стандартный компонент кнопки VCL использует КНОПКУ класса окна из общих элементов управления Windows.

Обратите внимание, что TSpeedButton не использует общий элемент управления Windows и не имеет этой проблемы. однако он также не принимает фокус.

Похоже, что Embarcadero знает об этой проблеме, это QC # 75246 , который закрыт, потому что это действительно ошибка в библиотеке общих элементов управления, поскольку не исправит, с предложением использовать TBitBtn . Не только кнопки, это часть группы отчетов QC, включая панели и другие общие элементы управления.

Однако у меня есть коммерческая кнопка TcxButton (часть экспресс-компонентов для разработчиков), которая принимает фокус клавиатуры и не отображает этот сбой. Похоже, что в любом коде, использующем общий элемент управления Win32 в виде кнопки, возникает эта проблема. Возможно, хакер низкоуровневого Win32 API найдет обходной путь для этого. Я изучаю это. Этот ответ будет обновлен, если я это выясню.

Одна интересная деталь: TcxButton имеет три стиля рисования, cxButton.LookAndFeel.Kind = {lfOffice11, lfFlat, lfStandard}. Выбор lfOffice11 добавляет этот сбой обратно. Это похоже на странное взаимодействие между функцией стекла в aero в Vista / Win7 и общим кодом рисования кнопки control / xptheme.

Возможно, единственный обходной путь - использовать полностью нарисованный приложением элемент управления-кнопку и не использовать кнопки общих элементов управления Windows или любой кнопочный элемент управления, который использует механизм тем XP для рисования кнопок на аэродинамической стеклянной панели.

Редактировать: 28 июля кто-то в Embarcadero закрыл вышеупомянутую запись в QC, что было ошибкой. Я призываю их снова открыть его, хотя бы для того, чтобы уточнить, действительно ли это ошибка Windows в dll общих элементов управления.

Если вы хотите поиграть, сделайте копию исходного кода VCL для классов TButton и TCustomButton из StdCtrls, как я сделал здесь, измените CNCtlColorBtn, чтобы принудительно выполнить одно из трех: PerformEraseBackground, DrawParentBackground или унаследованный, и посмотрите результаты. Интересный материал.

procedure TCustomGlassButton.CNCtlColorBtn(var Message: TWMCtlColorBtn);
begin
  PerformEraseBackground(Self, Message.ChildDC);
  Message.Result := GetStockObject(NULL_BRUSH);
(*
  with ThemeServices do
    if ThemesEnabled then
    begin
      if (Parent <> nil) and Parent.DoubleBuffered then
        PerformEraseBackground(Self, Message.ChildDC)
      else
        DrawParentBackground(Handle, Message.ChildDC, nil, False);
      { Return an empty brush to prevent Windows from overpainting we just have created. }
      Message.Result := GetStockObject(NULL_BRUSH);
    end
    else

      inherited;
  *)
end;

Некоторые интересные материалы по API-интерфейсам Glass / DWM / aero эпохи Vista (блог разработчиков C ++)

2
ответ дан 4 December 2019 в 02:25
поделиться

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

1
ответ дан 4 December 2019 в 02:25
поделиться
Другие вопросы по тегам:

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