Похоже, что единственным обходным решением является рисование владельцем или сторонний элемент управления Проверьте 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 ++)