Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Практикум программирования на С++ под Windows #10


Служба Рассылок Subscribe.Ru проекта Citycat.Ru

Практикум программирования на C++ под Windows
comp.soft.prog.cppwin
Выпуск #10
2001-01-08

*** Рисование II ********************************************************

И это же надо! Рассылка 2 (два) месяца не выходила, а динамика подписки на нее осталось той же. Это нечто.

Краткое содержание предыдущих выпусков

  #1  Вводная по рассылке
  #2  Вводная по курсу
  #3  Вводная по средствам
  #4  Введение в C++
  #5  Среда программирования
  #6  Консоль
  #7  Введение в C++. Продолжение
  #7A Выбор среды программирования
  #7B Вопросы и ответы
  #8  Простейшая оконная программа
  #8A ПРИЛОЖЕНИЕ. Текст простейшей оконной программы
  #8B Внеочередной выпуск (исправления, глоссарий)
  #8C Пояснения
  #9  Рисование
  #9A История Windows API

Отрисовка по необходимости

Часто возникает необходимость нарисовать что-либо на экране немедленно, не дожидаясь того, что система об этом попросит (сообщением WM_PAINT) - например, во время обработки события мыши. Но рисовать можно только в контекст (device context, DC). В обработке WM_PAINT возникал особый случай: контекст получался вызовом BeginPaint и возвращался системе вызовом EndPaint. В случае отрисовки по необходимости приходится поступать по-другому:

  HDC hdc = GetDC(hWnd); //Берем у системы контекст для нашего окна
  ... //Рисуем
  ReleaseDC(hWnd, hdc); //Возвращаем экран системе

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

Системы координат

Система координат, используемая при рисовании, является целочисленной. Начало координат расположени в левом верхнем углу окна. Ось Ox направлена вправо, ось Oy - вниз. Точка экрана - это минимальный неделимый элемент - пиксел (pixel) - квадрат со стороной 1, который окрашен в некоторый цвет. Координаты пиксела - это координаты его левого верхнего угла.

При рисовании центр системы координат можно искусственно сдвинуть:

  SetViewportOrgEx(hdc, x,y, NULL); //Считать началом координат точку (x,y)
Этот сдвиг будет действовать все время до окончания рисования в данном DC.

Кроме координат окна используются т.н. экранные координаты (screen coords) - координаты относительно левого верхнего угла всего экрана. Перевод из оконных координат в экранные и обратно выполняется функциями ClienToScreen и ScreenToClient соответственно.

Рисование через XOR

Логическая операция "исключающее или" (eXclusive OR, XOR) обладает одним полезным свойством. После выполнения присваиваний

  a1 <- a XOR b;
  a2 <- a1 XOR b;
будет выполняться равенство a2 = a. Т.е. повторное применение ксорирования с одним и тем же аргументом (b) приводит к полному восстановлению исходного значения (a). Естесственно, что эту операцию можно применять как с булевыми переменными, так побитово - с каждым битом числа. Последнее означает, что ксорирование возможно между двумя значениями любого типа, в том числе - цветами пикселов на экране. В последнем случае повторное рисование линии одним и тем же цветом но том же самом месте приведет к ее пропаданию. Такой "алхимический" эффект можно применять для организации динамичных эффектов без перерисовки всего изображения.

Режим рисования по XOR для перьев включается вызовом:

  SetROP2(hdc, R2_NOTXORPEN);

Попробуйте в режиме XOR нарисовать отрезок два раза на одном и том же месте. Что получиться?

Стандартные кисти и перья

Используя соответствуюие функции, мы можем создать перо или кисть любого цвета. Но для наиболее употребимых цветов перья и кисти уже есть. Для их получения применяется функция GetStockObject. С ее помощью можно получать перья - белое (WHITE_PEN), черное (BLACK_PEN) и невидимое (NULL_PEN), такие же кисти (WHITE_BRUSH, BLACK_BRUSH и NULL_BRUSH) и некоторые другие объекты.

 //Рисование незакрашенного прямоугольника
  HGDIOBJ hOldBr = SelectObject(hdc, GetStockObject(NULL_BRUSH)); //Подставляем
      // в контекст пустую кисть
  Rectangle(hdc, 20,10, 200,100); //Рисуем прямоугольник
  SelectObject(hdc, hOldBr); //Восстанавливаем status quo

Стандартные объекты можно (но не нужно) удалять функцией DeleteObject.

Контрольные вопросы (не нужно присылать мне ответы)

  1. Можно ли рисовать вне той части DC, которая видна через окно?
  2. Нужно ли после использования пера (pen), кисти (brush) удалять его?
  3. Что произойдет если я не буду удалять какой-нибудь маленький
     графический объект?
  3. Что произойдет, если мы выберем графический объект в DC, а затем
     удалим его не освободив из DC? Он будет удален?
  4. Сколько пикселов будет закрашено при помощи следующих вызовов:
       MoveToEx(0, 0, NULL);
       LineTo(2, 0);


*************************************************************************
Количество подписчиков: 7867
Архив Рассылки

Никита Зимин, г.Ижевск
Nikita_Zeemin@mail.ru



http://subscribe.ru/
E-mail: ask@subscribe.ru
Поиск

В избранное