Форум: Форум C++Разное
Новые темы: 00
PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум C++

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Мигание изображения.
 
 автор: alex19921992   (27.02.2007 в 12:18)   письмо автору
 
 

Когда я прогаю на Вин АПИ, я рисую в окошке. И при перерисовывании все мигает. Как сделать, чтоб не мигали? Мне друзья делали, но объяснить так и не смогли. там был какой-то битмап, два ХДЦ (на одно окно).... больше не помню. Может расскажете?

  Ответить  
 
 автор: cheops   (27.02.2007 в 12:32)   письмо автору
 
   для: alex19921992   (27.02.2007 в 12:18)
 

Приёмы разные бывают, например, но суть в том, чтобы заставить программу как можно меньше перерисовывать, точно определяя прямоугльник, который объявляется для перирисовки и не перерисовывая всё остальное. Более того, перерисовывать окно следует вообще как можно реже, обычно действительно всё содержимое окна помещается в bitmap, и когда происходит изменение в окно подставляется этот bitmap, который вы перерисовываете только в крайнем случае - когда что-то изменяется в самом окне.

  Ответить  
 
 автор: alex19921992   (27.02.2007 в 12:38)   письмо автору
 
   для: cheops   (27.02.2007 в 12:32)
 

А вы мне не объясните принцип действия этого:

// WM_CREATE
hdc=GetDC(hwnd);
GetWindowRect(hwnd, &pRect);
scrwidth = pRect.right - pRect.left;
scrheight = pRect.bottom - pRect.top;
phdc = CreateCompatibleDC(GetDC(hwnd));
pBmp = CreateCompatibleBitmap(hdc, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
SelectObject(phdc, pBmp);
//WM_PAINT
draw(pHdc);
//draw:
void Draw(const HDC destDC)
{
BeginPaint(hwnd, &ps);

myrectangle(destDC, 0,0,scrwidth, scrheight, GetSysColorBrush(COLOR_BTNFACE));//типа очищаем экран //рисуем
BitBlt(hdc, 0, 0, scrwidth, scrheight, pHdc, 0, 0, SRCCOPY);
EndPaint(hwnd, &ps);

}

  Ответить  
 
 автор: oleg_alexeev   (27.02.2007 в 14:27)   письмо автору
 
   для: alex19921992   (27.02.2007 в 12:38)
 

Мигание происходит по той причине, что перерисовка окна происходит в два приёма.
Сначала оконная процедура получает сообщение WM_ERASEBKGND и закрашивает
окно цветом фона. Затем она получает сообщение WM_PAINT и рисует содержимое
экрана.

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

Приведенный код похож на то что нужно, но, по-моему, там есть ошибки. По крайней
мере есть неясности.

Если есть желание действительно разобраться - надо читать Петцольда.

  Ответить  
 
 автор: alex19921992   (27.02.2007 в 14:58)   письмо автору
 
   для: oleg_alexeev   (27.02.2007 в 14:27)
 

Ну а где именно там ошибки?

  Ответить  
 
 автор: oleg_alexeev   (27.02.2007 в 16:19)   письмо автору
 
   для: alex19921992   (27.02.2007 в 14:58)
 

Похоже там просто опечатки. Наверное 'phdc' == 'pHdc'. Тогда должно работать.

Из недостатков:

1. Размеры окна запоминаются в момент создания окна. Работать корректно будет только если
размеры остаются постоянными.

2. В момент создания окна программа создает контекст устройства. Это совершенно не нужно,
так как он всегда создается при вызове BeginPaint.

3. Размер картинки для рисования выбирается равным размеру экрана. Это излишний расход
памяти, а при смене разрешения во время работы программы он может стать меньше
размера окна.

  Ответить  
 
 автор: alex19921992   (27.02.2007 в 17:03)   письмо автору
 
   для: oleg_alexeev   (27.02.2007 в 16:19)
 

1. Насчет размеров окна: это уже есть, просто я не вписал сюда, размеры запоминаются в WM_SIZE.
2. Как тут правильно сделать, подскажете?
3.Но я же рисую на все окно! Как сделать опитимальней?

  Ответить  
 
 автор: oleg_alexeev   (27.02.2007 в 21:01)   письмо автору
 
   для: alex19921992   (27.02.2007 в 17:03)
 

Вот вполне корректный код обработчика WM_PAINT:


PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);

RECT r, tmp;
GetClientRect(hWnd, &r);

HDC hdc_buf = CreateCompatibleDC(hdc);
HBITMAP hbm_buf = CreateCompatibleBitmap(hdc, r.right, r.bottom);
HBITMAP hbm_old = (HBITMAP) SelectObject(hdc_buf, hbm_buf);

HBRUSH hbr1 = CreateSolidBrush(RGB(0,100,200));
HBRUSH hbr2 = CreateSolidBrush(RGB(200,100,0));

// paint something
tmp = r; tmp.bottom = 30; FillRect(hdc_buf, &tmp, hbr1);
tmp = r; tmp.top    = 30; FillRect(hdc_buf, &tmp, hbr2);
TextOut(hdc_buf, 10, 20, "Hello world!", 12);
// put to screen
BitBlt(hdc, 0, 0, r.right, r.bottom, hdc_buf, 0, 0, SRCCOPY);

DeleteObject(hbr1);
DeleteObject(hbr2);

SelectObject(hdc_buf, hbm_old);
DeleteObject(hbm_buf);
DeleteDC(hdc_buf);

EndPaint(hWnd, &ps);


Не забудте в обработчике WM_ERASEBKGND вернуть 1.

Если смущает создание и удаление битмапа внутри WM_PAINT, то его конечно можно создать
в WM_CREATE, но придется отслеживать изменения размеров окна и изменения глубины цвета
экрана. Я бы оставил так (в основном так и поступают).

  Ответить  
 
 автор: alex19921992   (28.02.2007 в 04:38)   письмо автору
 
   для: oleg_alexeev   (27.02.2007 в 21:01)
 

А что за обработчик WM_ERASEBKGND? Надо просто в список сообщений вставить код

case WM_ERASEBKGND:return 1;

Так?

  Ответить  
 
 автор: oleg_alexeev   (28.02.2007 в 08:27)   письмо автору
 
   для: alex19921992   (28.02.2007 в 04:38)
 

Так

  Ответить  
 
 автор: alex19921992   (28.02.2007 в 13:50)   письмо автору
 
   для: oleg_alexeev   (28.02.2007 в 08:27)
 

Спасибо! А расшифровать приведенный код можно? А то неудобно работать с тем, что не знаю.

  Ответить  
 
 автор: oleg_alexeev   (28.02.2007 в 14:51)   письмо автору
 
   для: alex19921992   (28.02.2007 в 13:50)
 

Напишу только про то, что самому было трудно осознать:

DeviceContext - это набор атрибутов, используемых для рисования. Этими атрибутами являются
цвет текста, цвет подложки текста, текущая кисть (для закраски площадей), текущий шрифт и еще
много чего. Все они собраны в одном месте для того, чтобы вызов графических функций был
короче и нагляднее. При таком подходе TextOut имеет всего 5 параметров. Иначе было бы намного
больше.

Кроме того DeviceContext содержит указатель на область памяти, в которой собственно и происходит
рисование. Вызов SelectObject(hdc_buf, hbm_buf) как раз и задает картинку hbm_buf в качестве
этой памяти.

Про все остальное рекомендую читать Петцольда (несколько вечеров должно хватить).
Книжку могу прислать. А можно попросить уважаемого Хеопса выложить на сайте. Она уже не
издается вроде.

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования