реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Вопрос ламера про рисование, Visual с++
M_A
сообщение Jul 20 2005, 03:18
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 153
Регистрация: 27-12-04
Из: г. Иркутск
Пользователь №: 1 689



Я пока тока учусь, так что сильно не пинайте за глупые вопросы, просто много уже перерыл, а ответ не нашел.
Учусь рисовать в окне. Нарисовал примитивы типа круга, прямоугольника.
Завел цикл, где рисую круг со смещающимися координатами. Результат - куча выстроившихся друг за другом кругов. Вопрос: как после того, как нарисован круг, очистить окно, чтобы потом нарисовать второй со смещенными координатами и т.д. чтоб получить эффект "движущегося" круга?
З.Ы. просто у меня в идеале должна получиться железяка, передающая информацию из внешнего мира в комп, вот появилась идея отображать все графически, чтоб веселее было....
Go to the top of the page
 
+Quote Post
subver
сообщение Jul 20 2005, 04:15
Сообщение #2


Частый гость
**

Группа: Свой
Сообщений: 185
Регистрация: 4-06-05
Из: Омск
Пользователь №: 5 726



Смотреть в сторону функций BitBlt, CreateDIBSection и далее по MSDN smile.gif
получается очень аккуратно и быстро.
Go to the top of the page
 
+Quote Post
Kurt
сообщение Jul 20 2005, 05:43
Сообщение #3


Участник
*

Группа: Свой
Сообщений: 63
Регистрация: 16-06-04
Из: Россия, Уфа
Пользователь №: 31



На чем пишите?
Для того чтобы очистить экран перед отрисовкой следующей фигуры можно использовать функции GDI:

CRect rc;
GetClientRect(rc);

// clear background
dc.SetBkColor(::GetSysColor(COLOR_BTNFACE));
dc.ExtTextOut(0, 0, ETO_OPAQUE, rc, NULL, 0, NULL);

Еще стоит поискать в инете на тему flicker free drawing так как наверняка такая проблема возникнет.
Go to the top of the page
 
+Quote Post
M_A
сообщение Jul 20 2005, 07:35
Сообщение #4


Частый гость
**

Группа: Свой
Сообщений: 153
Регистрация: 27-12-04
Из: г. Иркутск
Пользователь №: 1 689



subver, Kurt Спасибо что откликнулись!

Я уже и сам кой-чего нашел!
Я был уверен, что есть какие то стандартные и простые решения для этого, вот одно из них и нашел (для MFC):

Invalidate(TRUE);
Go to the top of the page
 
+Quote Post
makc
сообщение Jul 20 2005, 10:28
Сообщение #5


Гуру
******

Группа: Админы
Сообщений: 3 621
Регистрация: 18-10-04
Из: Москва
Пользователь №: 904



Цитата(M_A @ Jul 20 2005, 10:35)
Invalidate(TRUE);
*


Это приводит к мерцанию, очень заметному на медленных машинах. Правильнее всего делать BitBlt для сохранения и восстановления изображения между выводом кругов.


--------------------
BR, Makc
В недуге рождены, вскормлены тленом, подлежим распаду. (с) У.Фолкнер.
Go to the top of the page
 
+Quote Post
M_A
сообщение Jul 21 2005, 01:48
Сообщение #6


Частый гость
**

Группа: Свой
Сообщений: 153
Регистрация: 27-12-04
Из: г. Иркутск
Пользователь №: 1 689



Цитата(makc @ Jul 20 2005, 10:28)
Цитата(M_A @ Jul 20 2005, 10:35)
Invalidate(TRUE);
*


Это приводит к мерцанию, очень заметному на медленных машинах. Правильнее всего делать BitBlt для сохранения и восстановления изображения между выводом кругов.
*



Про BitBlt почитал, вкратце он делает следующее:

Copies a bitmap from a specified device context.

Пните меня в нужном направлении, как это может мне помочь очищать окно?
Go to the top of the page
 
+Quote Post
subver
сообщение Jul 21 2005, 02:39
Сообщение #7


Частый гость
**

Группа: Свой
Сообщений: 185
Регистрация: 4-06-05
Из: Омск
Пользователь №: 5 726



Цитата
Пните меня в нужном направлении, как это может мне помочь очищать окно?


Очищать нужно не окно, а внеэкранный буфер.
BitBlt копирует с одного HDC на другой, один из них - DC вашего окна, другой - DC битмапа, который можно создать с помошью функции CreateDIBSection, вот пример:

Код
COLORREF *ScreenBuffer;
       ScreenBuffer = (COLORREF *)malloc(SCREEN_H*SCREEN_W*4);
       hdcDest=GetDC(Handle);
       bmi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
       bmi.bmiHeader.biWidth=SCREEN_W;
       bmi.bmiHeader.biHeight=SCREEN_H;
       bmi.bmiHeader.biPlanes=1;
       bmi.bmiHeader.biBitCount=32;
       bmi.bmiHeader.biCompression=BI_RGB;
       bmi.bmiHeader.biSizeImage=0;
       bmi.bmiHeader.biClrUsed=0;
       bmi.bmiHeader.biClrImportant=0;
       hdcSrc=CreateCompatibleDC(NULL);
       BitMap=CreateDIBSection(hdcSrc,&bmi,DIB_RGB_COLORS,&(void *)ScreenBuffer,NULL,0);
       SelectObject(hdcSrc,BitMap);
     
       /*здесь рисуем в ScreenBuffer
        .................................*/


      //А теперь копируем буфер на окно
       BitBlt(hdcDest,0,0,SCREEN_W,SCREEN_H,hdcSrc,0,0,SRCCOPY);


ScreenBuffer - выделенный блок памяти размером SCREEN_W*SCREEN_H*biBitCount/8 байт.

biBitCount - определяет количество битов на точку для нашего буфера (а не для окна), т.е. не зависит от текущего граф. режима видеокарты.

если biBitCount == 32, то формат цвета соответствует стандартному COLORREF.

Чтобы поставить точку с координатами 10,10 делаем так:
Код
ScreenBuffer[10+10*SCREEN_W]=color;


Соответственно, по окончании необходимо удалить все, что насоздавали:

Код
       DeleteObject(BitMap);
       DeleteDC(hdcSrc);
       free(ScreenBuffer);


Да, и еще - создавать и удалять буферы и битмапы надо при старте и закрытии приложения соответственно, а алгоритм отрисовки одного кадра такой:

1. Заполняем ScreenBuffer цветом фона
2. Рисуем все что нужно
3. Делаем BitBlt

Если возникает мерцание, то перед 3. надо дождаться обратного хода луча монитора, как это сделать сейчас не скажу, ибо не помню smile.gif
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 15th June 2025 - 21:00
Рейтинг@Mail.ru


Страница сгенерированна за 0.01417 секунд с 7
ELECTRONIX ©2004-2016