Форум: "Основная";
Текущий архив: 2003.10.13;
Скачать: [xml.tar.bz2];
ВнизМерцание при перерисовке Найти похожие ветки
← →
Raduga (2003-10-01 11:02) [0]Привет, мастера!
У меня такая проблема.
Создал компонент - потомок TgraphicControl, рисует изометрическое изображение цилиндра. Необходимо динамически закрашивать его часть (допустим от положения скролбара)во время работы программы. Если на форме много таких компонентов, то при перезакраске заметно мерцание, как от него избавится?
Спасибо.
← →
ZEE (2003-10-01 11:06) [1]> Raduga (01.10.03 11:02)
> Если на форме много таких компонентов, то при
> перезакраске заметно мерцание, как от него избавится?
- рисовать где-то в другом месте (битмам например) и потом BitBlt() ...
← →
Skier (2003-10-01 11:08) [2]
> Если на форме много таких компонентов, то при перезакраске
> заметно мерцание, как от него избавится?
TForm.DoubleBuffered := True; иногда помогает...
← →
Анонимщик (2003-10-01 11:40) [3]Лажа это. Смотрите хелп на слово wm_erasebkgnd
И пример в
Help\Examples\Bitmap в каталоге дельфи
← →
Danilcha (2003-10-02 12:36) [4]Не очень понятно объяснил. Но вообще-то для графики нужно TCustomControl использовать, а не TGraphicsControl -- последнй не окно, рисует на канве хозяина. Никаких DoubleBuffered не нужно. Но опять-таки -- а как ты рисуешь???
← →
Raduga (2003-10-02 13:34) [5]>Danilcha ©
Теперь рисую так: использую два битмапа, один сначала заливаю определенным цветом, потом рисую то что нужно, затем этот битмап
рисую на втором битмапе (через Draw второго) и второй на форму, через Draw формы. Все это делается в Paint моего компонента.
← →
Анонимщик (2003-10-02 15:23) [6]И что, помогает?
← →
Polevi (2003-10-02 15:41) [7]>Raduga (02.10.03 13:34) [5]
см Анонимщик © (01.10.03 11:40) [3]
← →
Knight (2003-10-02 18:21) [8]Смотри плюсом к wm_erasebkgnd ещё ValidateRect и InvalidateRect...
← →
Rem (2003-10-02 18:50) [9]WM_ERASEBKGND не всегда даст нужный результат. В данном случае, судя по тому, что сказано ("один сначала заливаю определенным цветом, потом рисую то что нужно"), все равно будет flicker. Поэтому лучше буферизировать.
← →
Knight (2003-10-02 19:07) [10]Не знаю, так же делал, только при перирисовке использовал
InvalidateRect(
HWND hWnd, // handle of window with changed update region
CONST RECT *lpRect, // address of rectangle coordinates
BOOL bErase // erase-background flag
);
bErase
Specifies whether the background within the update region is to be erased when the update region is processed. If this parameter is TRUE, the background is erased when the BeginPaint function is called. If this parameter is FALSE, the background remains unchanged.
С bErase=FALSE;
И никакого даблбуфера и мерцания...
← →
Polevi (2003-10-02 19:44) [11]>Rem © (02.10.03 18:50) [9]
он в буфере заливает, все правильно
← →
Rem (2003-10-02 20:38) [12]2 Polevi
В общем случае он будет делать это и на форме. Иначе останется мусор от предыдущих прорисовок. Кроме этого, на практике приходится рисовать пересекающиеся графические примитивы, что будет вызывать flicker.
Характерный пример - многие CAD программы: когда производится прорисовка большого количества объектов, это можно отчетливо наблюдать на экране. И им следовало бы использовать буфферизацию, чего они не делают. Возможно, это диктуется требованиями прикладной области? Не знаю...
А рисование на битмапе в памяти происходит быстрее, чем на экране.
Получается, что отрисовать сложный объект (тысячи примитивов) в памяти, а затем вывести полученный растр на экран - это быстрее, чем рисовать то же самое сразу же на экран.
← →
Polevi (2003-10-02 20:53) [13]не понимаю о чем спор
заливаем битмап в памяти, рисуем не него, в OnPaint делаем BitBlt, в ERASEBACKGROUND ничего не делаем
я понял что он так и поступает, мерцать ничего не должно
← →
Danilcha (2003-10-02 22:59) [14]Raduga,
Смотри.
1 -- Говрим только о TWinControl, т.к., как я уже говорил, TGraphicsControl не является окном, его Canvas -- окно в канвас хозяина. Им можно заменить, но осторожно и потом -- легче добиться стабильной работы с TCustomControl (потомок TWinControl со своей канвой). В принципе, разница небольшая, но когда приходиться его двигать или перекрывать одним другой, TCustomControl предпочтительнее, чем TGraphicsControl.
2. -- DoubleBuffered -- для ленивых. Лучше всё руками делать.
3. -- WM_ERASEBKGND и вообще, как рисуются окна. Когда окно появляется на экране (TCustomControl -- окно), сначала оно (при чём все новые окна сразу, до рассылки им WM_PAINT) получает WM_ERASEBKGND, на которое должно себя очень быстро залить цветом фона (стереть картинку, которая была на экране до появления этого окна). Заметь -- даже если мы оставим Paint() пустым (он WM_PAINTом вызывается) -- всё равно окно быдет рисоваться своим цветом. Затем окнам рассылаются уже эти самые WM_PAINT, на которые они себя, может быть, долго, рисуют. При чём если тебе нужно рисовать не на всей площади окна, рисуя, например, круг, свободное пространство заливать уже нет необходимости. Теперь, когда ты вызываешь Update, окну пошлёться лишь сообщение WM_PAINT.
4. -- Update(), Invalidate(), Refresh(). Update кладёт в очередь сообщений сообщение WM_PAINT, но лишь кладёт. Ты в своей процедуре можешь его хоть 30 раз вызвать -- ничего не произойдёт. Когда управление опять передастся цыклу выборки сообщений, на все WM_PAINT один раз вызовется Paint() -- окно себя нарисует, при чём лишь своё конечное состояние. Это очень умно. Inavalidate заставляет прямо сейчас просмотреть очередь и, если в ней есть WM_PAINT, удалить их и вызвать Paint. Refresh делает просто Update и Invalidate сразу, т.е. говорит окну, что пора перерисовать, и -- что вот именно сейчас.
5. -- теперь о твоей проблеме -- если можно всё рисовать в один слой -- например, залить фоном лишь то, что нужно стереть и нарисовать новое в новом месте -- лучше битмап вообще не использовать -- с ним медленнее. Если обязательно что-то при рисовании перекроется -- да, нужно использовать DDB, но всего один. При чём рисовать в нём не на каждый Paint, а только тогда, когда поменялась картинка. А так его хранить всё время готовым, на Paint лишь шлёпать его методом Canvas.Draw(). И всё. Голову даю -- мерцать не будет. Кстати, если делаешь анимацию -- плюнь на красоту, т.е. Refresh или Update -- сразу Paint вызывай -- будет быстрее.
6. -- ну и последнее -- если рисуешь по пикселям -- тоже нужен битмап, но уже DIB. Но это сложнее :)
Всё, надеюсь, тебе полегчало :) Удачи!
← →
Raduga (2003-10-03 08:45) [15]>Danilcha © (02.10.03 22:59) [14]
Огромное спасибо.
Мерцание прекратилось после прямого вызова Paint, без Invalidate.
← →
Danilcha (2003-10-03 09:20) [16]Ага, точно! Он всё-таки на Update посылает ещё и WM_ERASEBKGND! Хммм... Тогда Knight правильно написал
И ещё пардон, я местами Update() и Invalidate() перепутал! Давно я за Делфи не садился.... Как легко всё забывается...
Сейчас исходники посмотрел. Так вот, ещё -- есть такой ControlStyle и в нём csOpaque. Он то и говорит, нужно ли делать WM_ERASEBKGND на Invalidate. Достаточно было просто его установить или наоборот, уже не буду так уверенно утверждать :)
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.10.13;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.01 c