15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Битовые образы. Контекст памяти.

 

Автор статьи: 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чало страницы

Упражнения

  1. Нарисовать несколько объектов в окне. Поменять местами половинки окна.
    Готовый проект на VC++ 5.0.
  2. Поменять местами половинки экрана. Примечание: CreateDC ( "DISPLAY", 0, 0, 0) - контекст, позволяющий работать со всем экраном.
    Готовый проект на VC++ 5.0.
  3. Создать 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  
  4. Выполнить задание 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