2010-07-26 3 views
10

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

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

White borders around Delphi controls http://i30.tinypic.com/1zzqfm0.png

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

+2

У вас есть источники для минимального применения, показывающие это поведение? (.dfm и .pas простой формы) –

+0

@Jeroen: Я могу воспроизвести это поведение с помощью простой формы, содержащей TButton и устанавливающий стеклянный каркас, чтобы кнопка была на стекле. Я просто не могу подключиться к QC в данный момент, поэтому я не могу узнать, есть ли подобная ошибка, уже поданная. –

+0

Интересное поведение - когда button.doublebuffered - true, но форма doublebuffered - false, я получаю один цвет (черный) вокруг кнопки, и когда оба значения true, я получаю другой цвет (как указано выше, серый или clBtnFace), и когда кнопка не имеет двойной буферизации, текст выглядит серым. Таким образом, невозможно использовать кнопку на стекле в delphi 2010, если она не выглядит как дерьмо? –

ответ

5

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

+3

+1 для изящного мышления. Но, конечно, это никогда не бывает так просто :-( BitBtn отлично выглядит без двойной буферизации, когда форма не имеет двойной буферизации. Но включите ее для формы, а BitBtn будет выглядеть одинаково. Отключите ее для формы, а ярлыки исчезают Aaargh! –

+0

TSpeedButton отлично выглядит, когда я пытаюсь его здесь, но он не принимает фокус клавиатуры. –

+0

В Delphi XE TBitBtn работает отлично - независимо от установки DoubleBuffered на TBitBtn или в форме. Это мое предпочтительное решение –

2

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

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

В стандартном компоненте кнопки VCL используется клавиша Window Class BUTTON из общих элементов управления Windows.

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

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

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

Одна интересная деталь: TcxButton имеет три стиля рисования, cxButton.LookAndFeel.Kind = {lfOffice11, lfFlat, lfStandard}. Выбор lfOffice11 снова добавляет этот сбой. Это похоже на странное взаимодействие между стеклянным элементом в aero в Vista/Win7 и общим кодом рисования кнопки управления/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; 

Some interesting reading on Vista era glass/DWM/aero APIs (C++ developers blog)

1

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

0

Если вы можете использовать win32 api, попробуйте использовать уведомление NM_CUSTOMDRAW (а не ownerdraw), так как я делаю (да, кнопки посылают его, включая радио и флажки, для этого лучше всего использовать WM_CTLCOLORSTATIC.). Вот как это делается на C++, но идея такая же. Хотя моя идея хорошая, бывает так, что мои кнопки делают DISAPPEAR один раз для выполнения программы из окна, когда они настраиваются, и мне нужно навести курсор мыши на них, чтобы они снова были видны. Вот почему я все еще ищу для этого комментарии. Обратите внимание, что очень трудно воспроизвести исчезающие кнопки в приложениях с одной формой. Я все время испытываю такое поведение в каждом проекте.

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; 
Смежные вопросы