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

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

Очень Древний Баг с прозрачностью (DoubleBuffered)


Galkov ©   (2009-06-10 22:14:00) 

Есть такой баг-демо:
Program test;
uses  windows,kol;

var MainForm,ChildForm,Label1,Label2:PControl;

begin
 Applet    := NewApplet('Bug-Demo');
//главная форма
 MainForm  := NewForm (Applet, 'Main Form').SetPosition(120,120).SetSize(400,200);
 Label1    := NewLabel(MainForm, 'TEST-1').SetPosition( 20, 20);
 Label1.Transparent := true;
//дочерняя форма
 ChildForm := NewForm (MainForm, 'Child Form').SetPosition(220,220).SetSize(400,200);
 Label2    := NewLabel(ChildForm,'TEST-2').SetPosition( 20, 20);
 Label2.Transparent := true;
//поехали...
 Run(Applet);
end.


По неким причинам, связанным с совместимостью, у меня в работе "правленная" 1.69
И там это исправлено. Т.е., мне известна причина баги, и способы ее устранения (чего уже не скажу про версию 2.88)
Просто я бесконечно удивлен "долгожительством" этой баги.
Может пора поправить, а ???


D[u]fa   (2009-06-16 09:59:00) [1]

Я предлагаю выложить все фиксы =) возможно коллективно удастся "впихнуть" в новую версию


Galkov   (2009-06-15 17:20:00) [2]

Если в я чего решил, то выпью обязательно :D

Да, надо бы еще как-то придумать, как выделить из своих фиксов в 1.69-й те, которыми в 2.88 и не пахнет...
Кроме SetCurIndex еще парочка-то -- точно найдется... Больше, наверное...


D[u]fa   (2009-06-15 10:05:00) [3]

Ну мнение авторов примерно отражено в 9 посте)
Поэтому могу только пожелать свободного времени и удачи, либо забить до новых багов =)


Galkov   (2009-06-15 08:56:00) [4]

Ваша правда, коллега - остались. Это я глухо тупанул, Sorry:(

Да фигня все это. Чудес не бывает
Исправлю, да и все... Один раз справился (с 1.69), и второй раз - тоже справлюсь.
Кстати говоря, пытался "ее" насиловать аналогичными методами - ничего не вышло, все чистенько до противности. Похоже, что объем тестирования у нас был не хуже, чем здесь. Мягко говоря...
Вот выберу свободное время только.
Если уж Авторы отмалчиваются :(


D[u]fa   (2009-06-14 22:05:00) [5]

А у меня они остались =\
хотя с OLD_TRANSPARENT артефактов нет... КОЛ все же библиотека для создания компактного кода, поэтому кому надо то будет использовать OLD_TRANSPARENT.... и вот когда через Х лет найдет новый баг, тогда его и будут исправлять))


Galkov   (2009-06-14 20:58:00) [6]

Вот же ж блин :shock:
Если вышеприведенный мной "якобы фикс" делать в таком виде (разница - жирная):

 if (Sender.fParent<>nil) and(not Sender.isForm)
 and Sender.FParent.fDoubleBuffered
 and (not Sender.fParentRequirePaint) then
 begin
   TR := Sender.BoundsRect;
   InvalidateRect(Sender.fParent.fHandle, @TR, true);
   ValidateRect(Sender.fHandle, nil);  //???--brandys???+
   exit;
 end;


-- то я перестаю наблюдать артефакты, которые я трудолюбиво описывал выше.
Че к чему...

Неужели получается, что теперь, для полного удовольствия -- осталось только придумать получение TR не тупо через BoundsRect, а через GetUpdateRect....


Galkov   (2009-06-14 20:43:00) [7]


> При OLD_TRANSPARENT глюка невидно почему не правильно то?

Это значит его будет видно кому-то через год.
Оставлять неразорвавшиеся мины в чистом поле, даже если нашел обходной путь - это не правильно. Правильно - обезвреживать мины.
"Мина", это когда по WM_PAINT в ClildForm он делается валидным, зато инвалидся MainForm.
А делается именно так: коллега Hallifв это место пальцем ведь показал.
Ну не нарисует MainForm ничего в ChildForm. Просто, чтобы это увидеть - нужны, наверное, более тонкие примеры... Которые рано или поздно появятся.
И вот мне кажется, что правильней не искать эти примеры ради самих примеров, а мину напрочь обезвредить, а потом уже ждать примеров.


> какие другие?

а) минимизируем ChildForm, и видим артефакты на MainForm
б) более того, усмотреть артефакты на MainForm можно и без фикса. Убираем прозрачность с Label1 (просто комментируем строку в стартовом примере) - типа все правильно работает и без фиксов. Дулю с маком, на самом деле.
Передвигаем ChildForm, чтобы он перекрывал Label1, и опять минимизация.
Вот вам и артефакты на Label1


D[u]fa   (2009-06-14 11:00:00) [8]

При OLD_TRANSPARENT глюка невидно почему не правильно то? оО
И при NEW_TRANSPARENT после добавления (not Sender.isForm) тоже бага нет...


> - то стартовой баги не видно. Зато становятся видны другие
> :)


какие другие?


Galkov   (2009-06-12 22:59:00) [9]

Hallifвот Вы пальцем показали на ValidateRect, и соответствующий InvalidateRect для Sender.fParent
Это категорически неправильно для случая, когда этот парент является owner-ом
Неправильно, и все тут.
Тут даже не очень важно, успел ли кто придумать визуализацию этого "неправильно".
Не, ну можно сказать: " нет контр-примера - нет ошибки".
Сказать-то можно, а ошибка - будет, еще через год... Ну нельзя же всю жизнь делать один и тот же код.

В принципе, если приведенный Вами код из NEW_TRANSPARENT заменить на такой (кстати, первое условие там - это уже "давно проверенное" условие):

 if (not Sender.isForm)
 and Sender.FParent.fDoubleBuffered
 and (not Sender.fParentRequirePaint) then


- то стартовой баги не видно. Зато становятся видны другие :)

В общем, надо ставить "трассировщики", и со всем аккуратно разбираться.
Правда мне казалось, что сделать это авторам сих TRANSPARENT-ов было бы на порядок проще :(


Hallif   (2009-06-12 19:20:00) [10]

Galkov, попробуйте с директивой OLD_TRANSPARENT
Начиная с версии 2.24 введена функция WndProcTransparent, которая на данный момент представлена в двух вариантах: базовая и модифицированная фаст-версия (автор Александр Карпинский). В фаст-версии  часть условий была вынесена из цикла обработки сообщений.
В частности, эпизод WM_PAINT:  

ValidateRect(Sender.fHandle, nil);
   if (Sender.fTransparent) and (not Sender.fParentRequirePaint) then begin
                    InvalidateRect(Sender.fParent.Handle, nil, FALSE);
                    Result := TRUE;

теперь находится в несколько измененном виде под условием

if (Sender.fTransparent or Sender.fDoubleBuffered)
 and (Sender.FParent <> nil)
 and Sender.FParent.fDoubleBuffered
 and (not Sender.fParentRequirePaint)  then…

Предположительно для дочернего контролла существует альтернативный вызов при
fTransparent =0, fDoubleBuffered=1
Решением в данном случае, будет скорее всего замена части условия на
if (Sender.fTransparent or (not Sender.fDoubleBuffered)…
или вообще на   if Sender.fTransparent …


D[u]fa   (2009-06-11 15:07:00) [11]

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


Galkov   (2009-06-11 11:23:00) [12]

Дык они отличаются как небо и земля. И не всегдав лучшую сторону :)

А смысл очень простой: получивши ivalidate в нижнем контролле, мы всегда "передаем" его на верх. Тому, кто и будет рисовать на самом деле.
Так вот: не надо передавать енто паренту тупо, на ФОРМЕ следует таки остановиться.
Вот и вся премудрость...

В старых версиях этим делом занимался TControl.DblBufTopParent, и в нем фикс элементарен:

function TControl.DblBufTopParent: PControl;
var Ctl: PControl;
begin
 Result := nil;
 Ctl := @ Self;
 while Ctl <> nil do
 begin
   if Ctl.fDoubleBuffered then
     Result := Ctl;
   if Ctl.isForm then exit; // <-- да вот он
   Ctl := Ctl.fParent;
 end;
end;


Это пригодно только для демонстрации смысла сказанного, естественно


D[u]fa   (2009-06-11 10:35:00) [13]

дык выложил бы исправление хотя бы для старой версии


Наверх

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