Автор
|
Тема: Как рисовать?
|
BigBalls |
опубликован 11-01-2002 11:24 MSK
Обрисую проблему: На диалоге надо прорисовывать область, где выводится график некоего техпроцесса (типа осцилографа). Область небольшая, но при рисовании по Canvas (Builder) мерцает. Переписал обработчики WM_PAINT'а на API, от мерцания не избавился. Подскажите пожалуйста как быстро обновлять область, в каком направлении хоть искать?
|
al
|
опубликован 11-01-2002 11:51 MSK
Несколько советов по борьбе с мерцанием:Обязательно обрабатывать WM_ERASEBKGND и не рисовать фон! В противном случае всегда будет рисоватся сначала фон (в WM_ERASEBKGND), а потом само изображение (в WM_PAINT), что и вызывает мерцание. Второе. Как я понял, все рисуется в обработчике WM_PAINT. Если это так, то при изменении данных для отображения в "осцилографе" для его окна вызываеотся InvalidateRect() и (возможно) UpdateWindow(). На мой взгляд при изменении данных следует рисовать "картинку" непосредственно в контексте окна (получаемом через GetWindowDC()) - так будет несколько быстрее. |
ADK
|
опубликован 11-01-2002 11:58 MSK
Насчёт WM_ERASEBKGND согласен. непосредственно в контексте окна - полный гон, во-первых, это не даёт требуемого эффекта, во вторых, в обработчике OnPaint можно рисовать только в контексте, получаемом через BeginPaint, т.е CPaintDC. Я бы посоветовал создать отдельный класс для осциллографа и не рисовать на диалоге, так никто не делает. Просто потом проще прогу поддерживать будет. |
africa
|
опубликован 15-01-2002 17:12 MSK
Обычно такие вещи делаются через двойную буфферизацию. Рисуешь в памяти, а потом переносишь это куда тебе надо. |
the_moon
|
опубликован 15-01-2002 19:03 MSK
//Обычно такие вещи делаются через двойную буфферизацию. Рисуешь в памяти, а потом переносишь это куда тебе надо. А почему это называется двойной буфферизацией? :-| |
michl_m
|
опубликован 15-01-2002 19:34 MSK
1. Насчет WM_ERASEBKGND - это 100%. Если не перехватить, будет плохо. 2. Рисовать, конечно, лучше в WM_PAINT. Но, очевидно, тебе нужно обновлять по таймеру(осцилограф, все-таки). Если по таймеру сделать GetWindowDC(), GetDC() и подобное, отличное от BeginPaint(), то система скорее всего сгенерирует еще и WM_PAINT, в результате ты нарисуешь дважды, в лучшем случае. Это значит, что по таймеру нужно вызывать InvalidateRect() и UpdateWindow(). Причем InvalidateRect(myhWnd, NULL, FALSE)- не будет WM_ERASEBKGND. 3. Даже если и рисовать в WM_PAINT, то лучше действительно в памяти и затем BitBlt() или SetDIBitsToDevice(). 4. Проблема, наверно, в том, что фон все равно нужно вытирать - график-то изменился. Закрашивать его весь - довольно медленно. Если в памяти - то мерцания, конечно, не будет. Но можно попытаться вот что: рисовать в XOR режиме ( SetROP2(hDC, R2_XORPEN)). Рисуешь второй раз старый график - то бишь вытираешь. |
rodion
|
опубликован 16-01-2002 11:30 MSK
Проблема решается просто, надо синхронизировать рисование с движением луча монитора. Для этого в начале обработчика WM_PAINT вызвать beginpaint а в конце endpaint. |
ADK
|
опубликован 16-01-2002 11:54 MSK
2rodion: что ты имел в виду: "Для этого в начале обработчика WM_PAINT вызвать beginpaint а в конце endpaint". Если у меня ещё не совсем крыша едет, то по другому WM_PAINT и не обработать. CPaintDC тоже так делает. |
eyes
|
опубликован 16-01-2002 12:03 MSK
>Проблема решается просто, надо синхронизировать рисование с движением луча монитораОткуда данные что Винды это не делают? Все равно рисуете в контексте дивайса, он находится не в видеопамяти, это не ДиректХ |