Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > Delphi: Звук, графика и видео > Форма "моргает". Как сделать перерисовку быстрой? |
Автор: Гость_Александр 27.6.2004, 11:42 |
Добрый день! Пишу программу, которая строит расписание дежурств. На самой важной форме, отображающей это самое расписание визуально, сидит чёртова туча компонентов. И когда форма по какой-то причине (изменение размера, открытие-закрытие панели и т.п.) отрисовывает себя по новой, это выглядит, как нервный тик - всё начинает "моргать" и дёргаться. Прошёл по списку компонентов, выставил всем DoubleBuffer. "Моргать" перестало, но время отрисовки формы выросло настолько, что можно чуть ли не кофе попить, пока она приводит себя в порядок. Думаю, я не первый сталкиваюсь с такими вещами. Кто уже решал подобные проблемы - поделитесь опытом, плиз! Спасибо заранее. |
Автор: Borland_Delphi_6 27.6.2004, 12:39 |
У меня похожая проблема: Timage должен двигаться, из-за этого его сильно глючит ![]() |
Автор: ZLDO 27.6.2004, 12:50 |
Зачем двигать TImage? Нужно двигать изображение на TImage, а чтобы не моргало нужно всё прорисовывать в памяти (например временных TBitmap), а потом за один раз выдавать на экран - ...Canvas.Draw или BitBlt |
Автор: <Spawn> 27.6.2004, 18:21 |
Гость_Александр у тебя какая машина, что так тормозит от DoubleBuffered? И зачем для каждого контрола ее выставлять? Достаточно для формы поставить. У тебя точно на таймерах\потоках ни чего не сидит? |
Автор: Гость_Александр 28.6.2004, 13:02 |
Машина - второй пень. Тормозит она не так страшно, но задержка в несколько секунд с прорисовкой - это хреново. Просто на форме много всякого понавешано. Насчёт DoubleBuffered для формы - ты знаешь, если выставить для формы или если выставить для каждого компонента, программа ведёт себя по-разному. |
Автор: dm9 29.6.2004, 04:02 | ||||
Borland_Delphi_6, насчёт TImage. Передо мной стояла задача периодической перерисовки изображения - всё работало очень плавно. Двигать Image - изврат. Я бы просто перерисовывал изображение на канве парента с новыми координатами. Делается так. Сам обработчик onPaint:
(Подумав) О, Господи. А теперь надо рассказать, как по-простому загрузить картинку в HBitmap, как использовать CreateDIBSection... А сейчас 5 утра. В общем, извините. Если ЭТО кому-то надо - будет. Если нет - то нет. Просто сейчас писать про всё это очень не хочется... ![]() Добавлено @ 04:03 Если интересно - напишите, и завтра я опишу всё подробно. |
Автор: Borland_Delphi_6 29.6.2004, 15:31 |
dm9 Нужно, нужно ![]() |
Автор: dm9 2.7.2004, 21:38 |
Borland_Delphi_6, что-то я тогда загнался ![]() DIB - это хорошо, но в данном случае совершенно ни к чему. Просто создаёшь динамически j : TJPEGImage, грузишь туда картинку и затем отрисовываешь картинку на форме: Form1.Canvas.Draw (X, Y, j); Единственное, можно допустить такую ошибку. На таймере или как там поставить изменение координат X и Y, и затем написать Form1.Repaint или Form1.Refresh. Тогда будет моргать. А надо писать просто Form1.Canvas.Draw (X, Y, j). Всё плавно - я проверил. На на onPaint форсы тоже на забыть отрисовку. А то тут хотел уж рассказывать, как работать с DIB и DDB ![]() |
Автор: Borland_Delphi_6 3.7.2004, 16:34 | ||||
Смысл этого предложения мне не понятен... ![]() И еще. Вот у меня был такой код:
(это что-то вроде скринсевера) Как мне теперь узнать аналог Image1.Left и Image1.Top? |
Автор: dm9 4.7.2004, 01:39 |
Borland_Delphi_6, в простейшем случае я имел в виду это (см. файл). Если более сложно - там надо писать ещё обработчик onPaint для формы и делать не столь халявную перерисовку. Добавлено @ 01:39 PS Там что-то типа 5 килобайт... |
Автор: Borland_Delphi_6 4.7.2004, 13:14 |
dm9 Спасибо, примерчик очень хороший! Тока я взялся попробовать написать эту прогу на API, а то уж слишком большая она получается. ![]() |
Автор: dm9 4.7.2004, 14:44 |
Borland_Delphi_6, О! А вот здесь тогда как раз понадобится работа с DIB ![]() И отрисовку делать надо будет, как я написал. Будет время - скину примерчик. |
Автор: Borland_Delphi_6 4.7.2004, 15:12 | ||
dm9 Спасибо, как раз хотел тебе попрасить об этом ![]()
|
Автор: dm9 5.7.2004, 17:03 |
Вот тебе примерчик отрисовки, всё на чистом WinAPI. (Не мой). Что там тебе ещё надо. Таймер? ![]() Да, и не забывай всякие DeleteDC, DeleteObject, etc. Кстати, мои эксперименты показывают, что при такой отрисовке BeginPaint и EndPaint не спасают от мерцания почему-то... Это если движение картинки делать. Добавлено @ 17:04 PS Компиляция - запуск батника. Там < 30 кБайт. |
Автор: Albinos_x 5.7.2004, 17:27 |
имеются две фазы обновления окна. 1. привыводе окна винда посылает сообщение WM_ERASEBKGND, оповещяющее онеобходимости стирания фона перед процедурой рисования. Затем посылается сообщение WM_PAINT, служащее сигналом для закрашивания. Первое сообщение можно пропустить а) форсируя обновление самому с помощью вызова функции InvalidateRect(Handle, Nil, False) ; б) Можно указать VCL не стирать фон ControlStyle := ControlStyle + [csOpaque]; В этом случае от моргания можно избавиться. PS: Второй выриант в ХР не срабатывает почему-то (имею ввиду, что всё равно моргает), первый не проверял, но работать должен. |
Автор: Borland_Delphi_6 5.7.2004, 17:29 | ||
Тогда не катит ![]() |
Автор: Albinos_x 5.7.2004, 17:36 |
Borland_Delphi_6 мой вариан не пробовал? |
Автор: dm9 5.7.2004, 19:23 |
Borland_Delphi_6, на этих BeginPaint-ах свет клином не сошёлся. Их можно вообще не использовать. Albinos_x, я немного не то имею в виду. Если делать отрисовку тем способом, который я предложил, через BitBlt, то эта самая отрисовка происходит сразу же, мгновенно. Если поставить отрисовку между BeginPaint и EndPaint, ничего не меняется. Поэтому если мы делаем движение картинки таким образом: стираем фон, а затем рисуем картинку на новом месте, то получается мерцание. Я знаю только один способ, как сделать, чтобы процесс перерисовки не появлялся на экране - рисовать на дополнительном DC, созданном при помощи CreateCompatibleDC, а затем его отрисовывать на основной DC. Проблема в том, что при больших изображениях получается медленно. Можно, прада, применить хитрость. Если фон монотонный, то просто сделать окантовку картинке с таким же цветом и при плавном перемещении картинка сама будет закрашивать себя. Так я сделал в первом VCL-ном примере. PS Может быть, глюк с BeginPaint и EndPaint связан с тем, что у меня Win2003... |