и снова мерцание, hbrBackgroung , WM_ERASEBKGND и FillRectangle
От: galion  
Дата: 26.03.13 15:02
Оценка:
Вывожу текст в собственный контрол-окно. При прокрутке появляется эффект мерцания. Прочитал массу статей. Попробовал отключить прорисовку фона при регистрации контрола: wc.hbrBackgroung = 0. Мерцание ушло, но при этом при прокрутке не убирается "мусор" и фон не белый, а серый. Как нужно очищать "мусор" и как сделать фон белым? При попытке заполнения фона белым через FillRectangle мерцание вновь появляется
Re: и снова мерцание, hbrBackgroung , WM_ERASEBKGND и FillRectangle
От: CEMb  
Дата: 26.03.13 16:21
Оценка:
Здравствуйте, galion, Вы писали:

G>Вывожу текст в собственный контрол-окно. При прокрутке появляется эффект мерцания. Прочитал массу статей. Попробовал отключить прорисовку фона при регистрации контрола: wc.hbrBackgroung = 0. Мерцание ушло, но при этом при прокрутке не убирается "мусор" и фон не белый, а серый. Как нужно очищать "мусор" и как сделать фон белым? При попытке заполнения фона белым через FillRectangle мерцание вновь появляется


1. Нужно определиться, где будет отрисовка. WM_ERASEBKGND и/или WM_PAINT. Если бак рисуется родителем, то WM_ERASEBKGND return TRUE; При этом надо помнить, что WM_ERASEBKGND и WM_PAINT ставятся в очередь по разным событиям, по этим событиям и характеру рисования нужно выбирать, где рисовать. Мусор был в данном случае, потому что старое рисовалось поверх нового. Если отключать WM_ERASEBKGND, то нужно самому рисовать бак, например через FillRect(...); а потом выводить свой контент.

2. Дублирующая буферизация. Это чтоб не мелькало. Создаётся CreateCompatibleDC и CreateCompatibleBitmap, в них рисуется, и потом скидывается (по пункту №1) содержимое в изначальный DC через BitBlt, в общем случае.


HDC hdc = GetDC(hWnd);
HDC cdc = CreateCompatibleDC(hdc);
HBITMAP hBmp = CreateCompatibleBitmap(hdc, cx, cy);
HBITMAP hBmpOld = (HBITMAP)SelectObject(cdc, hBmp);
//... тут рисуем в cdc
BitBlt(hdc, 0, 0, cx, cy, cdc, 0, 0, SRCCOPY);
SelectObject(cdc, hBmpOld);
DeleteObject(hBmp);
DeleteDC(cdc);
ReleaseDC(hWnd, hdc);
// cx, cy - размер окна в общем случае
Re[2]: и снова мерцание, hbrBackgroung , WM_ERASEBKGND и FillRectangle
От: galion  
Дата: 26.03.13 17:30
Оценка:
CEM>1. Нужно определиться, где будет отрисовка. WM_ERASEBKGND и/или WM_PAINT. Если бак рисуется родителем, то WM_ERASEBKGND return TRUE; При этом надо помнить, что WM_ERASEBKGND и WM_PAINT ставятся в очередь по разным событиям, по этим событиям и характеру рисования нужно выбирать, где рисовать. Мусор был в данном случае, потому что старое рисовалось поверх нового. Если отключать WM_ERASEBKGND, то нужно самому рисовать бак, например через FillRect(...); а потом выводить свой контент.

что значит бак рисуется родителем? Фон я рисую в событии paint.
Обязательно ли делать буферизацию? я читал что можно без нее
FillRectangle приводит вновь к мерцанию
Re[2]: и снова мерцание, hbrBackgroung , WM_ERASEBKGND и FillRectangle
От: galion  
Дата: 27.03.13 08:47
Оценка:
CEM>2. Дублирующая буферизация. Это чтоб не мелькало. Создаётся CreateCompatibleDC и CreateCompatibleBitmap, в них рисуется, и потом скидывается (по пункту №1) содержимое в изначальный DC через BitBlt, в общем случае.

спасибо, вроде работает. фууух
Re[3]: и снова мерцание, hbrBackgroung , WM_ERASEBKGND и FillRectangle
От: CEMb  
Дата: 27.03.13 13:23
Оценка:
Здравствуйте, galion, Вы писали:


G>что значит бак рисуется родителем?


Ну, к примеру, есть у нас круглая на вид кнопка, а родительское окно залито градиентом.
Тогда wm_erasebkgnd кнопки потрёт часть родительского окошка, если не принять меры.
Можно в таких случаях перед отрисовкой вызвать рисовалку родителя, конкретно указав ему
в InvalidateRect прямоугольник ребёночного окна. При этом у него должна быть или нулевая кисть в окне
или просто wm_erasebkgnd return TRUE; После чего рисуем свой контент.
Вот тут есть пример, но без градиента.

G>Фон я рисую в событии paint.


Фон лучше рисовать как раз в wm_erasebkgnd, не принципиально, но всё же.
В 99% случаев тон однородный, и всё решается установкой кисти для окна, окно само фон рисует.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.