Битовые образы. Контекст памяти.
Автор статьи: Alexander E. Popov
Зачем вообще нужен bitmap? Существуют как
минимум две проблемы, которые можно решить с
помощью bitmap. Во первых: при рисовании в окне,
полученный рисунок нигде не хранится, поэтому
если вы довольно долго формировали рисунок, и вам
понадобилось перерисовать окно, может
получиться, что перерисовка занимает довольно
много времени. Во вторых, например, вы в OnPaint
случайным образом рисуете 10000 прямоугольников,
после чего ваше окно перекрывет другое окно.
Затем вы опять возвращаетесь к вашему
приложению, но часть окна, которая была перекрыта
другим окном, заново перерисовывется, но там уже
возникают другие случайные прямоугольники.
Поэтому нужно сохранять участки отображения в
памяти.
Bitmap имеет определенную структуру:
количество цветов, длина, ширина, количество
плоскостей, ...
CBitmap b; //пока не имеет размеров
Bitmap имеет смысл создавать такой же, как область
экрана, т.е. bitmap должен быть совместим с данным
экраном, точнее с данным типом отображения.
b.CreateCompatibleBitmap( pDC, //указатель на CDC
w, //ширина
h ) ; //высота
Не существует битовых образов для
обычных контекстов отображения (pDC - обычный
контекст).
CBitmap b ;
CClientDC dc ( this ) ;
b.CreateCompatibleBitmap ( &dc, 1024, 768 ) ;
Для того, чтобы рисовать на bitmap, нужно завести
специальный контекст, называемый контекстом
памяти, и выбрать этот bitmap в контекст памяти.
CDC memDC ; //оболочка MFC над объектом Windows.
//Сам объект создается по Create.
memDC.CreateCompatibleDC(&dc);
//Выберем bitmap в контекст
memDC.SelectObject( &b ) ;
//Теперь можно рисовать на bitmap. Хотя сейчас bitmap заполнен чем
//попало, поэтому если вы не будете заполнять полностью часть bitmap,
//выводимую на экран, то сначала bitmap нужно очистить, например
//с помощью FillRect.
memDC.Rectangle ( 10, 10, 100, 100 ) ;
Выведем bitmap на экран:
dc.BitBlt( x, y, w, h, //параметры экрана (куда рисовать)
&memDC,
x1, y1, //координаты левого верхнего угла, откуда рисовать
SRCCOPY ) ;
SRCCOPY учитывет только цвет источника, а цвет
приемника и цвет текущей кисти игнорируются.
Если режимы отображения различны (например: MM_TEXT
и MM_LOMETRIC), то произойдет преобразование координат
(может возникнуть проблема).
Есть режим вывода bitmap, при котором он
растягивается или сжимается:
dc.StretchBlt( x, y, w, h, //параметры экрана (куда рисовать)
&memDC,
x1, y1, w1, h1,
SRCCOPY ) ;
Чтобы использовать BitBlt и StretchBlt, не обязательно
иметь контекст памяти.
Перейти в нaчало страницы
Упражнения
- Нарисовать несколько объектов в окне. Поменять
местами половинки окна.
Готовый проект на VC++ 5.0.
- Поменять местами половинки экрана. Примечание:
CreateDC ( "DISPLAY", 0, 0, 0) - контекст, позволяющий
работать со всем экраном.
Готовый проект на VC++ 5.0.
- Создать 10 000 случайных прямоугольников в bitmap.
Последнее сделать в C...View::OnInitialUpdate. Bitmap и memDС
создать как данные-члены C...View. memDC
инициализировать в C...View::OnInitialUpdate.
OnInitialUpdate: for (int i=0; i< 10000; i++)
memDC.Rectangle(...
OnDraw:
pDC -> BitBlt( ..., &memDC, ...) ;
Готовый проект на VC++ 5.0
- Выполнить задание 3, добавив скролллинг. Для
чего представление породить от CScrollView.
В OnInitialUpdate добавть: CSize sizeTotal (1024, 768) ;
CSize sizePage (512, 384) ;
CSize sizeLine (30, 30) ;
SetScrollSizes(MM_TEXT, sizeTotal, sizePagem sizeLine) ;
Window пытается закрасить цветом кисти перед перерисовкой. Чтобы этого
избежать, в PreCreateWindow создать структуру класса с помощью
AfxRegisterWndClass (необходимо присвоить нулевую кисть) и породить
от него окно.
Готовый проект на VC++ 5.0
|