Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

TButton, Windows Vista/7, интересное поведение


gosha52 ©   (2010-07-16 13:05:00) 

Всем привет.
Ребята, особенно продвинутые в паскале, вы не обращали внимание, что кнопки созданные в дельфи с манифестом поддержки тем, ведут себя не совсем так, как ведут себя стандартные кнопки в Windows Vista/7 ? Я имею в виду плавные эффекты затухания когда фокус находится на кнопке и когда просто проводишь над кнопкой курсором мышки. Пробовал все версии дельфи, ничего не помогает, везде отсутствуют эти эффекты, вот и непонимаю почему. Версия контролов в манифесте вроде как 6.0 и это последняя на сегодня версия. Вообщем странно и хочется всё-таки понять по какой причине происходит такое досадное недоразумение. В инете покапал, что-то ничего не нашел. Главное в окнах стандартных диалогов эти эффекты присутствуют, т.к. создает их сама windows. Может кто-то сталкивался и нашел способ?


KilkennyCat   (2010-07-18 22:57:00) [1]


> 0x00FF00   (18.07.10 22:19) [16]

ну, всякие там турбопаскали с турбовиженом... у них тож явно проблемы будут.


0x00FF00   (2010-07-18 22:19:00) [2]


> любопытно так же делфи 4, 3, 2, 1, 0 и т.д.

Куда, в минус что ли?
Delphi (-1).0 %)


gosha52   (2010-07-18 18:32:00) [3]


> А вот TBitBtn является прямым потомком TButton и свойство
> DoubleBuffered у него все же есть.

Но это ему не поможет, т.к. кнопка рисуется внутри Buttons.pas.


KilkennyCat   (2010-07-17 20:26:00) [4]

любопытно так же делфи 4, 3, 2, 1, 0 и т.д.


Deltas   (2010-07-17 13:00:00) [5]

Кстати, в Delphi 5 и в Delphi 7, свойство DoubleBuffered описано как public (не published) и по умолчанию всегда установлено False.


Deltas   (2010-07-17 12:50:00) [6]


> gosha52   (17.07.10 12:29) [10]

Согласен. Судя по исходным текстам VCL DoubleBuffered, установленный равным False, приводит к обработке сообщений WM_ERASEBKGND, WM_PAINT по умолчанию.

> gosha52   (17.07.10 12:31) [11]

У TSpeedButton нет свойства DoubleBuffered, т.к. он не является потомком TWinControl. А вот TBitBtn является прямым потомком TButton и свойство DoubleBuffered у него все же есть.


gosha52   (2010-07-17 12:31:00) [7]

За исключением конечно всяких TBitBtn, TSpeedButton, где все рисуется внутри vcl.


gosha52   (2010-07-17 12:29:00) [8]


> А поподробнее? Для решения проблемы нужно DoubleBuffered
> для кнопки установить False?

Да, для кнопки, для комбобокса и любых других контролов, на которых не отображаются соответствующие эффекты.


Deltas   (2010-07-17 12:27:00) [9]


> gosha52   (17.07.10 12:20) [8]
> В общем проблема найдена, она зарыта в DoubleBuffered, который
> у меня True для формы, а значит и для всех контролов на
> этой форме по умолчанию.

А поподробнее? Для решения проблемы нужно DoubleBuffered для кнопки установить False?


gosha52   (2010-07-17 12:20:00) [10]


> Насколько я понимаю, класс окна TButton является суперклассом
> BUTTON только потому что оконная процедура TButton вызывает
> для обработки сообщений по умолчанию оконную процедуру класса
> BUTTON (ее адрес сохраняется в поле FDefWndProc).

Да, именно так и есть, иначе бы не рисовалась кнопка или любой другой "наследуемый" контрол.

В общем проблема найдена, она зарыта в DoubleBuffered, который у меня True для формы, а значит и для всех контролов на этой форме по умолчанию. Интресно, что TEdit при этом работает достаточно сносно с эффектами затухания своих границ.


Deltas   (2010-07-17 12:06:00) [11]

http://msdn.microsoft.com/en-us/library/ms633569(VS.85).aspx
Особое внимание в статье рекомендую обратить на
- window procedure subclassing
- window procedure superclassing

На самом деле, класс окна TButtonявляется суперклассом класса окна BUTTON(следуя терминологии MSDN). TButton отличается от BUTTON только названием класса и оконной процедурой (это видно из TButton.CreateWnd() в исходных текстах VCL). Насколько я понимаю, класс окна TButton является суперклассом BUTTON только потому что оконная процедура TButton вызывает для обработки сообщений по умолчанию оконную процедуру класса BUTTON (ее адрес сохраняется в поле FDefWndProc).

Вот еще одна статья на русском:
http://forum.vingrad.ru/forum/topic-69246.html
Но MSDN я всегда доверяю больше.


gosha52   (2010-07-17 11:58:00) [12]

Я проверил свою последнюю гипотезу и оказался не прав. Все эффекты присутствуют после создания кнопки с другим именем класса:

procedure TForm1.Button1Click(Sender: TObject);
var Params: TCreateParams;
begin
 if GetClassInfo(HInstance, 'BUTTON', Params.WindowClass) then
 begin
   Params.WindowClass.lpszClassName := 'TRealButton';
   if (Windows.RegisterClass(Params.WindowClass) > 0) then
     CreateWindowEx (0, 'TRealButton', 'Real Button', WS_CHILD or WS_VISIBLE or BS_PUSHBUTTON, 30, 30, 100, 50, Handle, 100, HInstance, nil);
 end;
end;


Видать мое первое предположение с проблемой в глубине VCL всё-таки наиболее верно. Попробую покапать TWinControl.


gosha52   (2010-07-17 11:10:00) [13]

Deltas,
Может я что-то недогоняю, но а что такое подкласс? CreateSubClass лишь получает информацию о классе и копирует все параметры в Params для регистрации своего класса, разве нет? Главное то, что в CreateWindowEx в конечном итоге передается TButton, а не BUTTON. Я думаю дело именно в том, что создается окно с другим именем класса, после чего винда перестает применять все эти эффекты к таким контролам.


Deltas   (2010-07-16 17:27:00) [14]


> gosha52   (16.07.10 15:58) [3]

Не все так просто.

procedure TButton.CreateParams(var Params: TCreateParams);
const
 ButtonStyles: array[Boolean] of DWORD = (BS_PUSHBUTTON, BS_DEFPUSHBUTTON);
begin
 inherited CreateParams(Params);
 CreateSubClass(Params, 'BUTTON');
 Params.Style := Params.Style or ButtonStyles[FDefault];
end;


Класс окнаTButton является подклассом BUTTON. И обработчик сообщений по умолчанию (DefWindowProc()) для окон класса TButton точно такой же как и у окон класса BUTTON.
И, если, окно класса BUTTON работает под Windows Vista (Windows 7) с плавными графическими эффектами, то ты прав - это проблема VCL. Но, для обхода проблемы не обязательно писать на чистом Win API, нужно покопаться в исходниках VCL и найти что именно приводит к некорректной работе кнопки.


gosha52   (2010-07-16 15:58:00) [15]

Для потомков:
Это проблема VCL, винда естественно и знать не знает о таком классе как TButton, который подсовывается в ClassName при создании контрола. Если вместо ClassName подсовывать BUTTON, то все будет работать как положено, но для этого нужно писать свой компонент, или использовать чистый win api.


gosha52   (2010-07-16 13:39:00) [16]

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


Deltas   (2010-07-16 13:34:00) [17]

Попробуй создать окно и кнопку в нем на чистом Win API (CreateWindowEx()). Возможно, в последних версиях Windows были добавлены новые стили окон и расширенные стили окон. Я тоже заинтересован в этом вопросе.


Наверх

Титульная страница Поиск, карта сайта Написать письмо