Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "KOL";
Текущий архив: 2008.04.27;
Скачать: [xml.tar.bz2];

Вниз

Как устранить флики   Найти похожие ветки 

 
Danger ©   (2007-06-22 21:00) [0]

Вопрос по ходу портирования одного компонента: как ликвидировать мигания при перерисовках контрола? (контрол представляет собой нечто вроде прогресс-бара, поэтому должен обновляться часто и без фликов).

Вот куски кода, ответственные за перерисовку:

// ----------------------------------------------------------
function QProgBar_WndProc( Control: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
var
PaintStruct: TPaintStruct;
begin
Result := False;
case Msg.message of
 WM_PAINT:
  begin
   BeginPaint( Control.Handle, PaintStruct );
   PQProgressBar( Control ).Paint;
   EndPaint( Control.Handle, PaintStruct );
   Result:= True;
   Rslt:= 0;
  end;
 WM_SIZE:
   PQProgressBar( Control ).Resize;
end; // case
end;


Функция QProgBar_WndProc аттачена к обработке событий при создании компонента:
// ----------------------------------------------------------
function NewQProgressBar( AParent: PControl ): PQProgressBar;
.........
begin
.........

Result.AttachProc( QProgBar_WndProc );
end;


Сама процедура отрисовки, полностью:

// ----------------------------------------------------------
procedure TQProgressBar.Paint;
// Main loop. Called each time a setting changes, notably, each time
// a new position is sent.
// Surround is drawn first, then the bar itself. Caption is added lastly (if needed).

var i,k,sp: Integer;
   OldBkMode : Integer;
   D: PQDataObj;
begin
 D:= PQDataObj( CustomObj );

 // -1- Bevel
 if ( D.fHasShape ) then
 with Canvas^ do
 begin
   Pen.PenWidth := 1;
   Brush.BrushStyle := bsSolid;
   Brush.Color := D.fBkgClr;
   Pen.Color   := D.fShapeClr;
   RoundRect (0, 0, Width, Height, D.fCorner, D.fCorner);
 end;

 // -2- The bar itself
 case D.fOrientation of
   boHorizontal :
     begin
       for i := ( D.fBorderSize - 1 ) to D.fPosition  do
       begin
         if ( D.fByBlock ) then
         begin
           if ( D.fPosDescr[i].isInBlock = true) then
           begin
             if  ( (D.fFullBlock) and (D.fPosition >= D.fPosDescr[i].blkLimit) )
             or not( D.fFullBlock ) then
             for k := (D.fBorderSize - 1) to (Height - (D.fBorderSize))
                      do Canvas.Pixels [i,k] := D.fPixDescr[i,k]
             else if (D.fShowInactPos) then
                     for k := (D.fBorderSize - 1) to (Height -(D.fBorderSize))
                         do Canvas.Pixels [i,k] := D.fInactDescr[k];
           end;
         end else
         begin
           for k := (D.fBorderSize - 1) to (Height -(D.fBorderSize)) do
               Canvas.Pixels [i,k] := D.fPixDescr[i,k];
         end;
       end;
       // Now dealing with inactive positions, if they"re to be drawn.
       if ( D.fShowInactPos ) then
       begin
         if (D.fPosition < 3) then sp := 3
         else sp := D.fPosition + 1;
         for i := sp to D.fUSefullDrawSpace do
         begin
           if (D.fByBlock) then
           begin
             if (D.fPosDescr[i].isInBlock = True) then
             begin
                for k := (D.fBorderSize -1) to (Height -(D.fBorderSize)) do
                      Canvas.Pixels [i,k] := D.fInactDescr[k];
             end;
           end else  //If not(byBlock), all pixels must be drawn
           begin
             for k := (D.fBorderSize - 1) to (Height -(D.fBorderSize)) do
                 Canvas.Pixels [i,k] := D.fInactDescr[k];
           end;
         end; {for}
       end; {inactive}
     end; {boHorizontal}
   boVertical :
     begin
       for i := (D.fUSefullDrawSpace-1) downto Height - D.fPosition  do
       begin
         if (D.fByBlock) then
         begin
           if (D.fPosDescr[i].isInBlock = true) then
           begin
             if  ( (D.fFullBlock) and ((Height - D.fPosition) <= D.fPosDescr[i].blkLimit) )
             or not( D.fFullBlock ) then
              for k := (D.fBorderSize - 1 ) to (Width - (D.fBorderSize))
                      do Canvas.Pixels [k,i] := D.fPixDescr[i,k]
             else if ( D.fShowInactPos ) then
                      for k := (D.fBorderSize - 1) to (Width -(D.fBorderSize))
                          do Canvas.Pixels [k,i] := D.fInactDescr[k];
           end;
         end
         else
          for k := (D.fBorderSize - 1) to (Width -(D.fBorderSize))
                      do Canvas.Pixels [k,i] := D.fPixDescr[i,k];
       end;
       // inactive positions :
       if (D.fShowInactPos) then
       begin
         if ( D.fPosition < 3 ) then sp := D.fUSefullDrawSpace
         else sp := Height - D.fPosition - 1;
         for i := sp downto D.fBorderSize do
         begin
           if ( D.fByBlock ) then
           begin
             if ( D.fPosDescr[i].isInBlock = true ) then
             begin
                for k := (D.fBorderSize - 1) to (Width -(D.fBorderSize)) do
                    Canvas.Pixels [k,i] := D.fInactDescr[k];
             end;
           end else
             for k := (D.fBorderSize - 1) to (Width -(D.fBorderSize))
                 do Canvas.Pixels [k,i] := D.fInactDescr[k];
         end; {for... downto}
       end; {inactive}
     end; {boVertical}
   end; // Case

   // caption management. The font is the canvas" one. Can be overrided
   // using the Font property :
   if ( D.fCaptionOvr ) then
      if ( D.fShowPosAsPct ) then _SetCaption( Double2Str( D.fUSerPosPct ) + "%")
      else SetCaption( Int2Str(D.fUSerPos) );
   if ( D.fHasCaption ) then
   begin
     OldBkMode := SetBkMode(Canvas.Handle, Windows.TRANSPARENT);
     with Canvas^ do
     begin
       TextOut(D.fCapPos.X, D.fCapPos.Y, Caption);
     end;
     SetBkMode(Canvas.Handle, OldBkMode);
   end;

end;


В чем может быть проблема, что при перерисовке контрол сильно мигает? Подскажитте, как можно исправить?


 
Vladimir Kladov   (2007-06-22 21:56) [1]

Мелькание происходит из-за того, что в процессе обновления сначала затирается прежнее изображение (цветом фона), а затем поверх него рисуется заново новое состояние. Если есть возможность обесчпечить рисование нового состояния без затирания предыдущего, то надо так и поступить. И не забыть в этом случае отработать WM_ERASEBKGND, ответив системе, что все уже сделано, и ничего делать не надо, иначе сама система по умолчанию займется созданием флика. Если такой возможности нет (изображение слишком сложное), то единственный выход - рисовать на битмапе в памяти, и перебрасывать все содержимое битмапа на DC в OnPaint. Как вариант этой возможности - DoubleBuffered := true - всего лишь создает такой битмап в памяти сам, и отрабатывает WM_PAINT и WM_ERASEBKGND на канву этого битмапа, после чего сам перебрасывает содержимое на экран. Следует только учесть, что все дочерние контролы такого контрола с двойной буферизацией так же рисуются на этом же битмапе в памяти.


 
homm ©   (2007-06-22 22:30) [2]

> Следует только учесть, что все дочерние контролы такого
> контрола с двойной буферизацией так же рисуются на этом
> же битмапе в памяти.

Неправда ваша. Только те у которых самих DoubleBuffered = true


 
Danger ©   (2007-06-23 09:42) [3]


> Vladimir Kladov   (22.06.07 21:56) [1]
> Как вариант этой возможности - DoubleBuffered := true -
> всего лишь создает такой битмап в памяти сам, и отрабатывает
> WM_PAINT и WM_ERASEBKGND на канву этого битмапа, после чего сам
> перебрасывает содержимое на экран.

DoubleBuffered решает проблему мигания, но появляется небольшая проблемка: рамка контрола изначально не прямоугольная (рисуется через RoundRect в процедуре Paint):

// -1- Bevel
if ( D.fHasShape ) then
with Canvas^ do
begin
  Pen.PenWidth := 1;
  Brush.BrushStyle := bsSolid;
  Brush.Color := D.fBkgClr;
  Pen.Color   := D.fShapeClr;
  RoundRect (0, 0, Width, Height, D.fCorner, D.fCorner);
end;

И при использовании DoubleBuffered у контрола появляются черные уголки, "спрямляющие" его в прямоугольник. В отрисовке без DoubleBuffered рамка отрисовывается нормально. Как заставить DoubleBuffered отрисовывать правильно?

>Следует только учесть, что все
> дочерние контролы такого контрола с двойной буферизацией так же
> рисуются на этом же битмапе в памяти.

Контрол не будет иметь потомков, поэтому несущественно.


 
Vladimir Kladov   (2007-06-23 11:18) [4]

Залить сначала тем цветом, которым надо чтобы были уголки.


 
Danger ©   (2007-06-23 15:08) [5]


> Vladimir Kladov   (23.06.07 11:18) [4]
> Залить сначала тем цветом, которым надо чтобы были уголки.

Спасибо, Владимир, сработало.


 
Jimmy Lee   (2007-08-27 19:59) [6]

Тестировал компонент. - все равно флики сильно заметные, если caBottom и таскать верхнюю границу. На мой взгляд сам метод align в KOL реализован не совсем оптимально. При ресайзе за верхнюю границу - нижняя прыгает как сумасшедшая. Что скажете? Тема далека от закрытия!


 
exero ©   (2007-08-28 08:47) [7]

В продолжение темы пример:
1. Кидаем на форму панель с Align = caClient
2. Кидаем на нее три панельки у первой Align = caTop у второй caBottom у третей caClient.
3. У нижней ставим все Anchor в True.
Запускаем - сворачиваем-разворачиваем - получаем совсем не ту картинку которую хотели (.

PS. Если OLD_ALIGN то все нормально.


 
Vladimir Kladov   (2007-08-28 21:15) [8]

2JimmyLee: разве в VCL меньше фликов или в любой другой программе в Windows, в том же проводнике? (Вы еще в Linux"е посмотрите, какие там флики в X-окнах, наши флики вам совсем незаметными покажутся). В принципе, с фликами бороться можно. Но - в каждом конкретном случае - отдельно. Кому-нибудь этот геморрой из разработчиков нужен?


 
danger ©   (2007-08-29 07:43) [9]


> Jimmy Lee   (27.08.07 19:59) [6]
> Тестировал компонент. - все равно флики сильно заметные,
>  если caBottom и таскать верхнюю границу.

В большинстве случаев флики в компонентах KOL такие же, как и в VCL аналогах. Не больше.

Касательно align для компонента - нужно обращаться к гуру KOL. Все это должно средствами библиотеки реализовываться. Не должно компоненту быть умнее библиотеки, отслеживание разных версий ALIGN"a и всевозможные фиксы для разных версий align"a не является задачей.


 
Vladimir Kladov   (2007-08-29 15:30) [10]

Если не бросать  панельку, а сразу на форму, то флики меньше. Сначала выравнивается то, что есть на формеЮ когда меняются ее размеры. Потом идёт каскадная обработка сообщения изменения размеров для дочерних панелей. И так далее, а поскольку изменение размеров - явление непрерывное и продолжается сколько-то во времени выравнивание выполняется многократно. В процессе окна перерисовываются, происходит обработка OnResize, если есть, и не факт, что всё это не тормозит процесс ещё больше.

Вывод: хотите убрать флики в конкретном приложении? Уберите все Align, при изменении размеров 1. вычислите все прямоугольники всех контролов сами 2. Присвойте новые координаты через BoundsRect :=. При этом, если ещё в процессе срабатывают какие-то ваши обработчики, сделайте так чтобы обработка шла потом, т.е. никакая отрисовка и никакие действия не выполнялись внутри вашей процедуры выравнивания.

Еще можно обрабатывать WM_WINDOWPOSCHANGING (так, кажется), и "правильно" задавать при этом, какие пиксели сдвигать, т.е. корректно определять только небольшую изменившуюся прямоугольную область, а остальное не перерисовывать (не всегда она оказывается внизу справа, но даже это по умолчанию Windows не используется, и инвалидируется весь контрол).


 
Andrey_rus ©   (2007-08-29 18:00) [11]

То, что флики KOL аналогичны фликам VCL, не повод успокаиваться. Я специально использую слабый компьютер (Celeron Pentium II - 300 Mz) для того чтобы воочию наблюдать медленную отрисовку контролов и соответсвенно предпринемать какие то действия. Однако на моем компбтере даже перегруженные контролами диалоговые окна MS Office отрисовываются моментально. Использование стандарного DoubleBuffer приносит больше вреда чем пользы (глюки с темами, не работает с RichEdit). Вот бы подумать сообща и реализовать собственный DoubleBuffer"инг. Это явно выделяло бы программы написанные на KOL и привлекло бы дополнительное количество разработчиков с VCL лагеря.


 
Jimmy Lee   (2007-08-29 18:41) [12]

Жаль нельзя аттачить в форуме, но если кто желает - могу прислать два примера:
1 KOL (форма->панель(align=caClient)->прогрессбар(алигн=caBottom))
2 Форма (не KOL), на ней панель(align=caClient) и на ней еще разные градиентные контролы, которые рисуются между прочим без BitBlt, а прямо в DC

во втором примере фликов намного меньше. для стресс-тестирования тягать окна надо за правый верхний угол.


 
homm ©   (2007-08-29 22:01) [13]

> [11] Andrey_rus ©   (29.08.07 18:00)
> Вот бы подумать сообща и реализовать собственный DoubleBuffer"инг.
> Это явно выделяло бы программы написанные на KOL.

http://www.delphimaster.ru/cgi-bin/nuts.pl?showpage=2
Первый пост про тебя :)


 
homm ©   (2007-08-29 22:02) [14]

> которые рисуются между прочим без BitBlt, а прямо в DC

Сегодня день перлов что-ли? :)


 
Andrey_rus ©   (2007-08-29 22:40) [15]

Зря ты homm, я ведь по делу.

Причем здесь написание файлового менеджера?

Лучше бы хотя бы предположил – как Office так быстро отрисовывает диалоговое окно с большим количеством на нем контролов.


 
homm ©   (2007-08-29 23:20) [16]

> Зря ты homm, я ведь по делу.

Да нет, не зря.


> Лучше бы хотя бы предположил – как Office так быстро отрисовывает
> диалоговое окно с большим количеством на нем контролов.

Временный битмап? Кто мешает его сделать в своем приложении?


 
Andrey_rus ©   (2007-08-29 23:24) [17]

> Да нет, не зря.
homm... homm...

> Временный битмап? Кто мешает его сделать в своем приложении?
Как?


 
homm ©   (2007-08-29 23:48) [18]

NewDibBitmap


 
Andrey_rus ©   (2007-08-29 23:56) [19]

>NewDibBitmap

Хороший пример... :)
homm, Не в обиду, хорош флуд разводить.


 
homm ©   (2007-08-30 00:04) [20]

> [19] Andrey_rus ©   (29.08.07 23:56)
> homm, Не в обиду, хорош флуд разводить.

пока ты ту флуд разводишь. Пока в КОЛ даблбуфер и transparent моей реализации, готов поспорить что когда исходник откроешь, у тебя духу не хватит в нем разобратся. Это пока единственная реализация работающая от 95 до висты. Наишешь лучше — возьму свои слова обратно, но пока, ты кроме как на тот орех, что я процетировал не тянешь.


 
homm ©   (2007-08-30 00:08) [21]

> Это пока единственная реализация работающая от 95 до висты.

Имеется ввиду не только КОЛ.


 
Andrey_rus ©   (2007-08-30 00:19) [22]

> пока ты ту флуд разводишь.
Где то я уже это видел... и не раз...

> Пока в КОЛ даблбуфер и transparent моей реализации
Огромное спасибо! Серьезно. Вот только пользоваться ими проблематично, по причине описанной мной выше.

>> Это пока единственная реализация работающая от 95 до висты.
> Имеется ввиду не только КОЛ.
А что еще?

Есть ли какие нибудь предположения относительно скорости прорисовки контролов в Office?


 
homm ©   (2007-08-30 00:33) [23]

> Есть ли какие нибудь предположения относительно скорости
> прорисовки контролов в Office?

Сделай скриншот, покажи, мне этьот контрол :)

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


> А что еще?
Все.


> Есть ли какие нибудь предположения относительно скорости
> прорисовки контролов в Office?
NewDibBitmap?


 
homm ©   (2007-08-30 00:43) [24]

Офис тоже не может похвастаться безглючной работой с темами. Пример прилагаеться:
http://homm86.narod.ru/files/office.png


 
homm ©   (2007-08-30 00:44) [25]

При многократном наведении эффект усиливаеться и контрол становиться почти черным.


 
Andrey_rus ©   (2007-08-30 00:51) [26]

> Сделай скриншот, покажи, мне этьот контрол :)
Открой в Office любое окно где много контролов.

> Пока в КОЛ даблбуфер и transparent моей реализации
> Это пока единственная реализация работающая от 95 до висты.
> Имеется ввиду не только КОЛ.
А что еще?
> Все.
Вывод - код, во всех библиотеках осуществляющих отображение контролов, написан тобой?


 
homm ©   (2007-08-30 00:57) [27]

> > Все.
> Вывод - код, во всех библиотеках осуществляющих отображение
> контролов, написан тобой?

НЕ верный вывод. Попробуй еше раз.


> [11] Andrey_rus ©   (29.08.07 18:00)
> не работает с RichEdit

Блин, что я вечно делаю не так? :)
http://homm86.narod.ru/files/rtf.rar


 
Andrey_rus ©   (2007-08-30 01:17) [28]


> НЕ верный вывод. Попробуй еше раз.

А по моему, все логично, перечитай свои посты.


> Блин, что я вечно делаю не так? :)http://homm86.narod.ru/files/rtf.rar


Тем, что предлагаешь для ознакомления в архиве - "Delphi 6 Release Notes
" и выполняемый файл неизвестного происхождения. Хочешь запустить мой. :)


 
homm ©   (2007-08-30 01:41) [29]

> [28] Andrey_rus ©   (30.08.07 01:17)
> и выполняемый файл неизвестного происхождения

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


 
exero ©   (2007-08-30 07:29) [30]

Уважаемый homm, хорош флудить! А что я делаю не так: качаем вашу прогу:
Load - Transparent - щелкаем на тексте и нажимаем клавишу стрелка влево (вправо) - что получится думаю увидите сами. А после этого скажите что никаких проблем нет и что это у меня кривые руки.


 
exero ©   (2007-08-30 07:51) [31]


> homm ©   (30.08.07 00:08) [21]
> > Это пока единственная реализация работающая от 95 до висты.
>


К сожалению это не так, под 98 (не поленился, проверил) тот же пример при включении прозрачности ведет себя некорректно - не отображает содержимое файла - оно появляется при щелчке мышкой и выделении - но у меня при потере фокуса окна содержимое снова пропадало.


 
homm ©   (2007-08-30 08:01) [32]

> А что я делаю не так:

Лучше чем есть все равно для RichEdit не сделать (тут ксати уж я совсем не причем, все вопросы к Microsoft). Единственное применение прозрачного RE — запретить в него вообще вставлять курсор.


 
exero ©   (2007-08-30 08:14) [33]

Я и не пытался найти виноватого, просто есть проблема и все.


 
Jimmy Lee   (2007-08-30 08:17) [34]

2 homm:

>  >Сегодня день перлов что-ли? :)

а что непонятного? или надо было расписать подробно, что графика де рисуется НЕ на битмапе с последующим трансфером этого битмапа на экран, а сразу в контексте устойства получаемом в BeginPaint, что в свою очередь, подразумевает медленный вывод графики, и что несмотря на это фликов все равно меньше?


> Пока в КОЛ даблбуфер и transparent моей реализации, готов
> поспорить что когда исходник откроешь, у тебя духу не хватит
> в нем разобратся.

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

Флики - это причина по которой я ваяю приложение без KOL, и мне очень тягостно далось это решение. В KOL очень многое реализовано, и писать самому - конечно лень. Но, приложение должно выглядеть профессионально, и не мерцать, когда его ресайзят, заказчик привередливый.


 
Jimmy Lee   (2007-08-30 08:31) [35]

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


 
homm ©   (2007-08-30 08:36) [36]

> [34] Jimmy Lee   (30.08.07 08:17)
> а зачем разбираться в чужом, глючном, да еще и медленном коде...

Ба, сколько эппитетов! :) Только «наезжать на всех это не сложно, но к сожалению не конструктивно». Сам то в этом как приуспел?


> А теперь о конструктивном:
Морево конечно :) «А теперь я выскажусь конструктивно: Давайте делайте что-б было все хоршо». Очень констрктивно :)



Страницы: 1 вся ветка

Форум: "KOL";
Текущий архив: 2008.04.27;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.58 MB
Время: 0.002 c
11-1173843627
ryslan56
2007-03-14 06:40
2008.04.27
Не работают библиотеки


3-1196339620
9899100
2007-11-29 15:33
2008.04.27
advantage odbc


3-1196335571
abhtr
2007-11-29 14:26
2008.04.27
Помогите составить запрос


11-1188198341
Dodfr
2007-08-27 11:05
2008.04.27
popupmenu unexpected closing


3-1196323881
MaShechka
2007-11-29 11:11
2008.04.27
Название колонок что делать???





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский