Кнопки Delphi показывают белую рамку на стекле Aero - PullRequest
10 голосов
/ 26 июля 2010

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

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

Белые границы вокруг элементов управления Delphi http://i30.tinypic.com/1zzqfm0.png

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

Ответы [ 4 ]

5 голосов
/ 26 июля 2010

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

2 голосов
/ 28 июля 2010

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

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

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

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

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

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

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

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

Редактировать: 28 июля кто-то на Embarcadero закрыл вышеуказанную запись КК, что было ошибкой. Я призываю их открыть его, хотя бы для того, чтобы уточнить, действительно ли это ошибка 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 эпохи Vista / DWM / Aero (блог разработчиков C ++)

1 голос
/ 30 июля 2010

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

0 голосов
/ 03 июля 2011

если вы можете использовать Win32 API, попробуйте использовать уведомление NM_CUSTOMDRAW (не владелец draw), как я (да, кнопки отправляют его, включая радио и флажки. Для них лучше использовать WM_CTLCOLORSTATIC.). Вот как это делается в C ++, но идея та же. В то время как моя идея хороша, так получилось, что мои кнопки ОТКЛЮЧАЮТСЯ один раз за выполнение программы из окна, когда они настраиваются, и мне нужно навести на них курсор мыши, чтобы они снова были видны. Вот почему я все еще ищу комментарии для этого. Обратите внимание, что действительно трудно воспроизвести исчезающие кнопки в приложениях с одной формой. Я испытываю такое поведение в каждом проекте.

case WM_NOTIFY:
  switch(((LPNMHDR)lParam)->code){
  case NM_CUSTOMDRAW:
    {
       NMHDR *nmh=(NMHDR*)lParam;
       //these 6000 through 6004 are button identifiers assigned by me
       if(nmh->idFrom >= 6000 && nmh->idFrom <= 6004){
         switch(((LPNMCUSTOMDRAW)nmh)->dwDrawStage){
           case CDDS_PREERASE:
             //BackgroundBrush is a HBRUSH used also as window background
             FillRect(((LPNMCUSTOMDRAW)nmh)->hdc, &((LPNMCUSTOMDRAW)nmh)->rc, BackgroundBrush);
             break;
         }
    }
    break;
}
break;
...