Вы находитесь на странице: 1из 19

Лекция 14 Работа с графикой 1

ЛЕКЦИЯ 14
КОНТЕКСТ УСТРОЙСТВА _______________________________________________________________ 2
Класс CDC и его производные ____________________________________________________________ 2
Объявление контекста___________________________________________________________________ 2
РАБОТА С ТЕКСТОМ ____________________________________________________________________ 3
Вывод текста. Функция TextOut ___________________________________________________________ 3
Вывод текста в прямоугольнике отсечения. Функция ExtTextOut ________________________________ 3
Цвет фона. Функции GetBkColor, SetBkColor _________________________________________________ 4
Цвет символов текста. Функции GetTextColor, SetTextColor_____________________________________ 4
Выравнивание текста. Функции GetTextAlign, SetTextAlign _____________________________________ 4
Пример рисования текста ________________________________________________________________ 5
ЦВЕТОВАЯ СИСТЕМА RGB ______________________________________________________________ 6
ДИАЛОГОВОЕ ОКНО ВЫБОРА ЦВЕТА ___________________________________________________ 7
Конструктор класса CColorDialog__________________________________________________________ 7
Отображение диалогового окна. Функция DoModal ___________________________________________ 7
Получение выбранного цвета. Функция GetColor _____________________________________________ 7
Получение дополнительных цветов. Функция GetSavedCustomColors ____________________________ 7
Пример использования диалогового окно выбора цвета _______________________________________ 8
МОДЕЛЬ ПЕРЬЕВОГО ПЛОТТЕРА________________________________________________________ 8
Перемещение карандаша. Функция MoveTo _________________________________________________ 8
Рисование отрезка. Функция LineTo ________________________________________________________ 9
Рисование точки. Функция SetPixel_________________________________________________________ 9
Получение цвета точки. Функция GetPixel ___________________________________________________ 9
РИСОВАНИЕ ГРАФИЧЕСКИХ ПРИМИТИВОВ ____________________________________________ 9
Рисование прямоугольника. Функция Rectangle ______________________________________________ 9
Рисование округлённого прямоугольника. Функция RoundRect __________________________________ 9
Рисование эллипса. Функция Ellipse ______________________________________________________ 10
Рисование эллиптической дуги. Функция Arc _______________________________________________ 10
Рисование эллиптической дуги и хорды. Функция Chord ______________________________________ 10
Рисование ломаной линии. Функция Polyline________________________________________________ 10
Рисование многоугольника. Функция Polygon _______________________________________________ 11
КАРАНДАШ. КЛАСС CPEN ______________________________________________________________ 11
Конструкторы класса СРеn ______________________________________________________________ 11
Создание карандаша. Функция CreatePen __________________________________________________ 12
Создание указателя на карандаш. Тип HPEN _______________________________________________ 12
Использование объекта. Функция SelectObject ______________________________________________ 12
Получение атрибутов объекта. Функция GetObject___________________________________________ 13
НАСТРОЙКА РЕЖИМА ОТОБРАЖЕНИЯ_________________________________________________ 13
Выбор единиц измерения. Функция SetMapMode ____________________________________________ 13
Задание произвольных единиц измерения. Функции SetViewportExt и SetWindowExt ________________ 14
Размер прямоугольника. Структура SIZE __________________________________________________ 14
Настройка начала координат. Функции SetViewportOrg и SetWindowOrg _________________________ 14
Получение размеров клиентской области. Функция GetClientRect ______________________________ 14
Пример настройки режима отображения ___________________________________________________ 15
КИСТЬ. КЛАСС CBRUSH ________________________________________________________________ 16
Конструкторы класса CBrush_____________________________________________________________ 16
Образец физической кисти. Структура LOGBRUSH __________________________________________ 16
Создание кисти________________________________________________________________________ 17
Пример создания и использования кисти __________________________________________________ 17
ТОЧЕЧНЫЙ РИСУНОК. КЛАСС CBITMAP _______________________________________________ 18
Создание точечного рисунка. Функция CreateBitmap _________________________________________ 18
Создание ресурса точечного рисунка _____________________________________________________ 18
Загрузка ресурса точечного рисунка. Функция LoadBitmap ____________________________________ 19

Выжол Ю.А.
Лекция 14 Работа с графикой 2

КОНТЕКСТ УСТРОЙСТВА
Контекстом устройства называется область памяти, используемая в системе Windows для выполне-
ния графических операций. Графический вывод может выполняться как на экран, так и на принтер. Объек-
ты класса CDC (Class Device Contacts) содержат множество встроенных методов, используемых в процес-
се рисования в контексте устройства. Все рисование в Windows выполняется через контекст устройства.
Контексты устройств упрощают задачи программирования. Дело в том, что они могут соответство-
вать самым разным устройствам, например, экрану монитора или принтеру. Если вы рисуете через кон-
текст устройства, то изображение будет правильно отображаться на разных устройствах, в том числе на
экране и на принтере без изменения кода.

CObject

CDC

CClientDC

CMetaFileDC

CPaintDC

CWindowDC

Класс CDC и его производные


Иерархия классов контекстов приведена на рисунке.
CDC – базовый класс для всех классов, инкапсулирующих контексты устройств Windows. Объекты
этого класса используются при работе с экраном дисплея или с принтером
CPaintDC – используется только в обработчике сообщения WM_PAINT
CСlientDC – используется только при работе с клиентской областью окна.
CWindowsDC – используется при работе со всем окном, как с клиентской, так и с неклиентской обла-
стью.
CMetaFileDC – используется при работе с метафайлами
Класс CDC имеет два члена данных для хранения дескрипторов:
HDC m_hDC – дескриптор контекста устройства графического вывода.
HDC m_hAttribDC – дескриптор контекста устройства используется для получения параметров уст-
ройства.
По умолчанию оба дескриптора равны.

Объявление контекста
Для рисования в клиентской области окна удобно использовать виртуальную функцию прорисовки
экрана. Она реализована в виде заглушки afx_msg OnPaint. Как правило, MFC Class Wizard сам добавля-
ет скелет кода этой функции в код класса диалогового окна.
class CGraphDlg : public CDialog
{
protected:
afx_msg void OnPaint () ;
DECLARE_MESSAGE_MAP ()

};

Выжол Ю.А.
Лекция 14 Работа с графикой 3
Функция OnPaint вызывается в тот момент, когда окно получает сообщение WM_PAINT. Это со-
общение посылается окну всегда, когда требуется перерисовка экрана. Например, при увеличении разме-
ра окна, если окно выходит на передний план, при запуске программы.
Поскольку наша программа должна реагировать на событие перерисовки экрана, то карта сообще-
ний должна содержать вызов соответствующей функции ON_WM_PAINT
BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd)
ON_WM_PAINT

END_MESSAGE_MAP()
Переопределяем функцию перерисовки окна.
void CMainWnd::OnPaint()
{
// объявление экземпляра класса CPaintDC для работы с клиентской областью окна
// связывает его с контекстом устройства текущего диалогового окна
CPaintDC dc ( this ) ;
dc.TextOut ( 200 , 200 , "Hello MFC Program" ) ; // Написать в окне привет
}
Если вам необходимо перерисовать окно не только при его увеличении, но и при уменьшении, то
целесообразно создать функцию обработки события изменения размеров окна, которая содержит команду
посылки сообщения WM_PAINT.
void CGraphDlg::OnSize ( UINT nType , int cx , int cy )
{
CDialog::OnSize ( nType , cx , cy ) ;
SendMessage ( WM_PAINT ) ; // посылаем команду родительскому окну перерисовать окно
}

РАБОТА С ТЕКСТОМ

Вывод текста. Функция TextOut


Для вывода текста в классе CDC определено два метода.
Назначение: рисует строку символов в указанном положении, используя текущий шрифт.
Синтаксис:
BOOL TextOut ( int x, int y, const CString& str ) ;
virtual BOOL TextOut ( int x, int y, LPCTSTR lpszString , int nCount ) ;
Возвращаемое значение: ненулевое, если функция успешно выполнена, и ноль в противном случае.
Параметры:
x, y определяет логические координаты строки.
lpszString указатель на строку символов, значение которой будет нарисовано.
str объект типа CString, значение которой будет нарисовано.
nCount определяет количество символов, которые будут нарисованы.
Замечания: по умолчанию, текущие координаты функцией не используются и не обновляются. Для ис-
пользования текущих координат нужно вызвать функцию SetTextAlign со значением параметра nFlags
равным TA_UPDATECP. Если флаг установлен, то вместо значений параметров x, y используются зна-
чения текущих координат.

Вывод текста в прямоугольнике отсечения. Функция ExtTextOut


Для вывода текста в прямоугольнике отсечения в классе CDC определено два метода.
Назначение: рисует строку символов в указанном положении, используя текущий шрифт; отсекает текст,
который вышел за границами заданного прямоугольника; позволяет изменить интервалы между символа-
ми.
Синтаксис:
BOOL ExtTextOut ( int x , int y , UINT nOptions , LPCRECT lpRect , const CString& str , LPINT
lpDxWidths ) ;

Выжол Ю.А.
Лекция 14 Работа с графикой 4
virtual BOOL ExtTextOut ( int x , int y , UINT nOptions , LPCRECT lpRect , LPCTSTR lpszString ,
UINT nCount , LPINT lpDxWidths ) ;
Возвращаемое значение: ненулевое, если функция успешно выполнена, и ноль в противном случае.
Параметры:
x,y определяет логические координаты строки.
lpszString указатель на строку символов, значение которой будет нарисовано.
str объект типа CString, значение которой будет нарисовано.
lpRect указатель на структуру RECT, которая определяет размеры и положение прямоуголь-
ника. Этот параметр может быть недействителен (NULL). Вы можете также использо-
вать объект типа CRect для этого параметра.
nCount определяет количество символов, которые будут нарисованы.
LpDxWidths указатель на массив целых чисел, которые определяют интервал между соседними
символами. Если параметр недействителен (NULL), то функция использует стандарт-
ный интервал между символами.
nOptions определяет тип прямоугольника, которые будут нарисованы.
Этот параметр может содержать одно, два, или ни одного из следующих значений:
ETO_CLIPPED текст, который вышел за границы прямоугольника, будет отсечен.
ETO_OPAQUE прямоугольник будет закрашен текущим цветом фона.

Цвет фона. Функции GetBkColor, SetBkColor


Система использует цвет фона, чтобы заполнить бреши между стилизованными линиями, бреши
между штрихуемыми линиями в щетках, и фон в ячейках символов. Получить и изменить цвет фона можно
с помощью следующих функций.
Синтаксис:
COLORREF GetBkColor ( ) const;
virtual COLORREF SetBkColor ( COLORREF crColor ) ;
Возвращаемое значение: Предыдущий цвет фона, если функция успешно выполнена, и 0x80000000 в
противном случае.

Цвет символов текста. Функции GetTextColor, SetTextColor


Получить и изменить цвет символов текста можно с помощью следующих функций.
Синтаксис:
COLORREF GetTextColor ( ) const;
virtual COLORREF SetTextColor ( COLORREF crColor ) ;
Возвращаемое значение: Предыдущий цвет символов текста.
Параметры:
crColor новое значение цвета символов текста.

Выравнивание текста. Функции GetTextAlign, SetTextAlign


Назначение: определяет способ выравнивания текста, который рисуется с помощью функций TextOut и
ExtTextOut. Определяет также способ использования текущих координат.
Синтаксис:
UINT GetTextAlign ( ) const ;
UINT SetTextAlign ( UINT nFlags ) ;
Возвращаемое значение: предыдущее значение флагов, если функция успешно выполнена, и ноль в
противном случае.
Параметры:
nFlags определяет способ выравнивания текста. Этот параметр может быть суммой одного или
нескольких флагов из трёх категорий. Можно выбирать только один флаг из каждой ка-
тегории.
Первая категория флагов определяет положение строки в горизонтальном направлении относи-
тельно x-координаты:
TA_CENTER координата определяет положение центра строки.
TA_LEFT координата определяет положение левого края строки (по умолчанию).

Выжол Ю.А.
Лекция 14 Работа с графикой 5
TA_RIGHT координата определяет положение правого края строки.
Вторая категория флагов определяет положение строки в вертикальном направлении относительно
y-координаты:
TA_BASELINE координата определяет положение базовой линии строки.
TA_BOTTOM координата определяет положение нижнего края строки.
TA_TOP координата определяет положение верхнего края строки (по умолчанию).
Третья категория определяет, обновлены ли текущие координаты после вызова функции вывода
текста:
TA_NOUPDATECP не обновляет текущую координату (по умолчанию)
TA_UPDATECP обновляет текущую x-координату. Новое положение находится с правой
стороны рабочего прямоугольника. Когда этот флаг установлен, координа-
ты, указанными в вызовах функции TextOut, не используются.

Пример рисования текста


Ниже приведён пример программы, которая в диалоговом окне изменяемого размера отображает синий
заголовок на сером фоне, белый прямоугольник и красный текст внутри прямоугольника. Текст выходящий за
границы прямоугольника отсекается. Вид диалогового окна приведён на рисунке.

Поскольку пользователю разрешено изменять размеры окна, то в программе предусмотрено масштабиро-


вание изображения – заголовок всегда располагается вверху экрана по центру, прямоугольник всегда занимает
центральную четверть экрана, текст рисуется в центре экрана. Масштабирование изображения достигается сле-
дующими мерами:
Рисование осуществляется в объявленной функции DrawText члене класса диалогового окна
CtextDlg.
Вызов функции в объявленной функции DrawText члене класса диалогового окна CtextDlg осуществ-
ляется в методе OnPaint, который вызывается при каждом изменении размеров экрана.
Размеры клиентской области окна определяются с помощью функции GetClientRect
void CTextDlg :: OnPaint ( ) // Функция перерисовки окна
{
DrawText ( ) ;
}
void CTextDlg :: DrawText ( ) // Функция рисования в окне
{
// объявление экземпляра класса CClientDC для работы с клиентской областью - текущего окна
CClientDC dc ( this ) ; // контекст устройства - текущее окно
CRect ClientRec ; // параметры клиентской области
CString Title = "Заголовок"; // объявление строки заголовка
CString Text = "Пример текста в рамке"; // объявление строки текста
COLORREF crBlue = RGB ( 0 , 0 , 255 ); // объявление синего цвета для текста
COLORREF crGray = RGB ( 232 , 232 , 232); // объявление серого цвета для фона
COLORREF crRed = RGB ( 255 , 0 , 0 ); // объявление красного цвета для текста
COLORREF crWhite = 0x00FFFFFF ; // объявление белого цвета для фона
GetClientRect ( &ClientRec ) ; // получение параметров клиентской области
int L=ClientRec.right ; // ширина диалогового окна
int H=ClientRec.bottom ; // высота диалогового окна
dc.SetBkColor ( crGray ) ; // установка цвета фона
dc.SetTextColor ( crBlue ) ; // установка цвета текста
// установка выравнивания текста: горизонталь - по центру, вертикаль - по базовой линии

Выжол Ю.А.
Лекция 14 Работа с графикой 6
dc.SetTextAlign ( TA_CENTER | TA_BASELINE );
dc.TextOut ( L/2 , 15 , Title ); // рисование заголовка в центре окна
CRect TextRec; // параметры текстовой области
// вычисление параметров текстовой области
TextRec.top =H/4; TextRec.left = L / 4 ;
TextRec.bottom = 3 * H / 4 ; TextRec.right = 3 * L / 4 ;
dc.SetBkColor ( crWhite ) ; // установка цвета фона
dc.SetTextColor ( crRed ) ; // установка цвета текста
dc.ExtTextOut ( L / 2 , H / 2 , ETO_OPAQUE | ETO_CLIPPED , &TextRec , Text , NULL ) ;
}

ЦВЕТОВАЯ СИСТЕМА RGB


В зрительной системе человека существуют три типа цветовых рецепторов – колбочек. Каждый тип
имеет свою зависимость чувствительности от длины световой волны. Максимумы этих кривых чувстви-
тельности располагаются в области красного, зелёного и синего цветов. Таким образом, мозг получает
информацию о цвете в виде набора трёх сигналов, а не в виде непрерывной функции.
Подводя итог сказанному, получим основополагающий принцип трехкомпонентной теории цветовос-
приятия: если два цвета характеризуются одним и тем же набором первичных составляющих, они
визуально неразличимы.
Прямым следствием принципа трехкомпонентной теории цветовосприятия является возможность
сформировать любой цвет как сумму первичных компонентов: красного (Red), зелёного (Green) и голубого
(Blue). Цветовое соответствие при этом выражается соотношением
C = T1 R + T2 G + T3 B
В современных графических API стало возможным обеспечить правильную цветопередачу, причем
аппаратно удается использовать алгоритмы аппроксимации, позволяющие достаточно приблизиться к
полноценной RGB-модели отображения.
Концептуально в RGB-системе наложения цветов должны существовать три раздельных буфера
кадра — по одному на каждый из первичных цветов. В каждом буфере за определенным пикселем на эк-
ране закреплен фиксированный адрес в памяти. В типовой системе, имеющей разрешение 1280╳1024 пик-
селей, каждый из них описывается тремя байтами (24 битами): по одному байту соответственно для
красного, зеленого и синего цвета. В результате буфер кадра должен иметь объем порядка 3 Мбайт, при-
чем весь буфер должен считываться с частотой регенерации.
В библиотеке MFC для хранения цвета определён тип COLORREF, который является синонимом
беззнакового целого числа unsigned int. Доля каждого из основных цветов кодируется числом от 0 до 255
и хранится в трёх младших байтах. Четвёртый байт используется для служебных целей.

S B G R

4 байта
Для инициализации переменной, которая хранит цвет, удобно использовать как шестнадцатеричную
систему исчисления, так и макрос RGB прототип которого имеет вид:
COLORREF RGB ( BYTE red , BYTE green , BYTE blue) ;
Выражения для основных цветов в виде шестнадцатеричной константы и с помощью вызова макро-
са RGB будут иметь вид:
Чёрный 0x00000000 RGB ( 0 , 0 , 0 )
Белый 0x00FFFFFF RGB ( 255 , 255 , 255 )
Светло-серый 0x00E4E4E4 RGB ( 232 , 232 , 232 )
Тёмно-серый 0x00A0A0A0 RGB ( 160 , 160 , 160 )
Красный 0x000000FF RGB ( 255 , 0 , 0 )
Зелёный 0x0000FF00 RGB ( 0 , 255 , 0 )
Синий 0x00FF0000 RGB ( 0 , 0 , 255 )
Жёлтый 0x0000FFFF RGB ( 255 , 255 , 0 )

Выжол Ю.А.
Лекция 14 Работа с графикой 7
Все цвета, которые имеют равные соотношения первичных компонентов, проявляются в виде оттен-
ков серого цвета.
Разложить цвет на составляющие можно с помощью макросов GetRValue, GetGValue, GetBValue.

ДИАЛОГОВОЕ ОКНО ВЫБОРА ЦВЕТА


Стандартное диалоговое окно Выбора цвета позволяет пользователю выбрать цвет из 48 цветов
основной палитры, а также определить дополнительные цвета. Диалоговое окно имеет вид, показанный
на рисунке.

Конструктор класса CColorDialog


Конструктор класса имеет следующий прототип:
CColorDialog ( COLORREF clrInit = DWORD , dwFlags = 0 , CWnd* pParentWnd = NULL ) ;
Параметры:
clrInit первоначально выбранный цвет (по умолчанию – черный);
dwFlags комбинация флагов, позволяющих, например, отобразить панель выбора дополнитель-
ных цветов или запретить ее использование;
pParentWnd указатель на родительское окно.

Отображение диалогового окна. Функция DoModal


Функция DoModal, определённая в классе CColorDialog, создает и отображает диалоговое окно
выбора цвета.
Синтаксис:
virtual int DoModal ( ) ;
Возвращаемое значение: IDOK или IDCANCEL – это константы, которые указывают, выбрал ли поль-
зователь кнопку OK или Отмена.

Получение выбранного цвета. Функция GetColor


Получить выбранный пользователем цвет можно с помощью функции GetColor, определённой в
классе CСolorDialog. Прототип этой функции имеет следующий вид:
COLORREF GetColor ( ) const ;
Функция возвращает выбранный пользователем цвет.

Получение дополнительных цветов. Функция GetSavedCustomColors


Диалоговое окно Выбора цвета позволяет кроме основного цвета позволяет определить до 16 до-
полнительных значений цвета с помощью функции GetSavedCustomColors, протопит которой, имеет вид:
Синтаксис:
static COLORREF* GetSavedCustomColors () ;
Возвращаемое значение: указатель на массив из 16 RGB-цветов.
Изначально каждый из элементов массива инициируется белым цветом.

Выжол Ю.А.
Лекция 14 Работа с графикой 8
Пример использования диалогового окно выбора цвета
Ниже приведён код обработки события щелчка на кнопке IDC_COLOR в классе CcolDlg.
void CColDlg :: OnColor ( )
{
// создание экземпляра класса окна выбора цвета; цвет по умолчанию - красный
CColorDialog dlg ( 0x000000FF ) ;
// вывод на экран окна выбора цвета
if ( dlg.DoModal ( ) == IDOK ) // если при закрытии окна пользователь нажал кнопку ОК
{
CString str ; // текст сообщения
COLORREF color ; // выбранный цвет
BYTE red , green , blue ;
// составляющие цвета
color = dlg.GetColor ();
// получение цвета, выбранного пользователем
red = GetRValue ( color ) ;
// определение красной составляющей цвета
green = GetGValue ( color ) ;
// определение зелёной составляющей цвета
blue = GetBValue ( color ) ;
// определение синей составляющей цвета
// Формирование строки текста сообщения, цвета выводятся в виде шестнадцатеричных чисел
str.Format ( "Выбран цвет 0x%08X, содержащий:\n"
"\t0x%02X - красного\n"
"\t0x%02X - зеленого\n"
"\t0x%02X - синего", color , red , green , blue ) ;
// вывод окна сообщений
MessageBox ( str , "Выбран цвет" ) ;
}
В результате работы этого фрагмента кода на экран будет выведено следующее окно сообщений.

МОДЕЛЬ ПЕРЬЕВОГО ПЛОТТЕРА


Большинство графических систем первого поколения были двухмерными. В них использовалась
концепция модели перьевого плоттера. Такое устройство формирует изображение на бумаге за счет пе-
ремещения пера, закрепленного на двух подвижных направляющих. Одна направляющая перемещается в
продольном направлении (вдоль оси у), а другая — в поперечном (вдоль оси х). Специальный механизм
поднимает и опускает перо. В опущенном состоянии перо при перемещении оставляет след на бумаге —
этот след и формирует изображение. В современных пакетах используется та же самая идея формирования
на носителе следа подвижного пера, т.е. фактически воспроизведения процесса ручного вычерчивания с по-
мощью карандаша. Пользователь при этом имеет дело с участком плоскости, ограниченным размерами
планшета.
Поведение такой графической системы описывается двумя основными графическими функциями: Move-
To и LineTo.
При выполнении функции MoveTo перо приподымается и затем перемещается в точку с координа-
тами (х, у), не оставляя следа на носителе. При выполнении функции LineTo перо опускается и затем пе-
ремещается по прямой из текущего положения в точку с заданными координатами (х, у), оставляя след на
носителе. Если добавить к этим функциям еще и функции настройки (выбор пера подходящего цвета и
толщины), то получим законченную двухмерную графическую систему. Ниже приведены прототипы этих
функций.

Перемещение карандаша. Функция MoveTo


Назначение: перемещает карандаш в указанную позицию.

Выжол Ю.А.
Лекция 14 Работа с графикой 9
Синтаксис:
CPoint MoveTo ( int x , int y ) ;
CPoint MoveTo ( POINT point ) ;

Рисование отрезка. Функция LineTo


Назначение: рисует отрезок от текущего положения карандаша до указанной точки с одновременным из-
менением текущего положения карандаша.
Синтаксис:
BOOL LineTo ( int x , int y ) ;
BOOL LineTo ( POINT point ) ;
Возвращаемое значение: ненулевое, если функция успешно выполнена, и ноль в противном случае.
Обе функции перегружены и допускают задание координат, как в виде пары чисел, так и с помощью
структуры POINT.

Рисование точки. Функция SetPixel


Назначение: рисует точку размером один пиксель (Picsel – PICtureS ELement). Размер точки зависит от
разрешения экрана.
Синтаксис:
COLORREF SetPixel ( int x , int y, COLORREF crColor ) ;
COLORREF SetPixel ( POINT point , COLORREF crColor ) ;
Возвращаемое значение: цвет нарисованной точки.
Параметры:
x,y определяет логические координаты точки.
point объект типа POINT, который определяет логические координаты точки.
crColor цвет точки.

Получение цвета точки. Функция GetPixel


Назначение: возвращает цвет точки с определёнными координатами.
Синтаксис:
COLORREF GetPixel ( int x , int y ) const ;
COLORREF GetPixel ( POINT point ) const ;
С помощью функции GetPixel можно, например, определить цвет диалогового окна и передать его
цвету фона при рисовании текста. В этом случае ваша программа не будет зависеть от настроек Windows.

РИСОВАНИЕ ГРАФИЧЕСКИХ ПРИМИТИВОВ


Класс CDC содержит широкий набор функций для рисования графических примитивов. Ниже при-
ведены прототипы некоторых из этих функций.

Рисование прямоугольника. Функция Rectangle


Назначение: рисует контур прямоугольника текущим карандашом и заполняет его текущей кистью. Теку-
щее положение карандаша не изменяется.
Синтаксис:
BOOL Rectangle ( int x1 , int y1 , int x2 , int y2 ) ;
BOOL Rectangle ( LPCRECT lpRect ) ;
Возвращаемое значение: ненулевое, если функция успешно выполнена, и ноль в противном случае.
Параметры:
x1 , y1 , x2 , y2 координаты двух противоположных вершин прямоугольника.
lpRect указатель на структуру RECT, которая определяет размеры и положение прямоуголь-
ника. Допускается также использование в качестве параметра объектов типа CRect.

Рисование округлённого прямоугольника. Функция RoundRect


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

Выжол Ю.А.
Лекция 14 Работа с графикой 10
на дуге. Дуга рисуется в направлении против часовой стрелки. Так как дуга не является замкнутой линией,
то заполнение текущей кистью не выполняется.
Синтаксис:
BOOL RoundRect( int x1 , int y1 , int x2 , int y2 , int x3 , int y3 ) ;
BOOL RoundRect ( LPCRECT lpRect , POINT point ) ;
Параметры:
x1 , y1 , x2 , y2 координаты двух противоположных вершин прямоугольника.
x3 , y3 размер эллипса, используемого для округления.
lpRect указатель на структуру RECT, которая определяет размеры и положение прямоуголь-
ника.
point размер эллипса, используемого для округления.

Рисование эллипса. Функция Ellipse


Назначение: рисует эллипс, вписанный в указанный прямоугольник, текущим карандашом и заполняет его
текущей кистью. Текущее положение карандаша не изменяется.
Синтаксис:
BOOL Ellipse ( int x1 , int y1 , int x2 , int y2 ) ;
BOOL Ellipse ( LPCRECT lpRect ) ;

Рисование эллиптической дуги. Функция Arc


Назначение: рисует эллиптическую дугу между двумя заданными радиус-векторами. Радиус-вектор начи-
нается в центре рабочего прямоугольника и заканчивается в указанной точке, которая не обязана лежать
на дуге. Дуга рисуется в направлении против часовой стрелки. Так как дуга не является замкнутой линией,
то заполнение текущей кистью не выполняется.
Синтаксис:
BOOL Arc ( int x1 , int y1 , int x2 , int y2 , int x3 , int y3 , int x4 , int y4 ) ;
BOOL Arc ( LPCRECT lpRect , POINT ptStart , POINT ptEnd ) ;
Параметры:
x1 , y1 , x2 , y2координаты двух противоположных вершин прямоугольника, в который вписан эллипс.
x3 , y3 координаты конечной точки начального радиус-вектора.
x4 , y4 координаты конечной точки конечного радиус-вектора.
lpRect указатель на структуру RECT, которая определяет размеры и положение прямоуголь-
ника, в который вписан эллипс.
ptStart указатель на конечную точку начального радиус-вектора.
ptEnd указатель на конечную точку конечного радиус-вектора.
Вместо структуры POINT допускается также использование объектов типа CPoint.

Рисование эллиптической дуги и хорды. Функция Chord


Назначение: рисует замкнутую линию, состоящей из эллиптической дуги между двумя заданными радиус-
векторами и соответствующей хорды. Радиус-вектор начинается в центре рабочего прямоугольника и за-
канчивается в указанной точке, которая не обязана лежать на дуге. Дуга рисуется в направлении против
часовой стрелки. Нарисованная фигура заполняется текущей кистью.
Синтаксис:
BOOL Chord ( int x1 , int y1 , int x2 , int y2 , int x3 , int y3 , int x4 , int y4 ) ;
BOOL Chord ( LPCRECT lpRect , POINT ptStart , POINT ptEnd ) ;
Параметры: те же, что и у функции Arc.

Рисование ломаной линии. Функция Polyline


Назначение: рисует набор отрезков, соединяющих указанные точки. В отличие от функции LineTo, функ-
ция Polyline не использует и не обновляет текущую координату.
Синтаксис:
BOOL Polyline ( LPPOINT lpPoints , int nCount ) ;
Параметры:
lpPoints указатель на массив структур POINT, которые определяют соединяемые точки.

Выжол Ю.А.
Лекция 14 Работа с графикой 11
nCount определяет количество точек в массиве (не менее 2)
Пример: В приведённом ниже примере создаётся массив точек, определяющих крест. Массив содержит 7
точек – 4 вершины и центр креста, который используется трижды. Крест рисуется с помощью ломаной ли-
нии с центром в точке x, y.
CClientDC dc ( this ) ; // контекст устройства – текущее диалоговое окно
const n = 7 ; // количество точек в массиве
int x = 200 , y = 100 ; // координаты центра креста
int h = 10 ; // длина луча
// объявление и инициализация массива вершин креста
POINT ptD [ n ] = {{ x-h , y } , { x , y } , { x , y-h } , { x , y } , { x+h , y } , { x ,y } , { x , y+h }} ;
dc.Polyline ( ptD , n ); // рисование креста

Рисование многоугольника. Функция Polygon


Назначение: рисует многоугольник, содержащий не менее двух вершин. Фигура всегда замкнута – если
необходимо, то функция соединяет отрезком первую и последнюю вершины.
Синтаксис:
BOOL Polygon( LPPOINT lpPoints , int nCount ) ;
Параметры: те же, что и у функции Polyline .
Текущий способ заполнения многоугольника может быть получен и задан с помощью функций
GetPolyFillMode и SetPolyFillMode.

КАРАНДАШ. КЛАСС CPEN


Класс СРеn инкапсулирует графический объект Windows – “карандаш”. Карандаши используются
для рисования различных линий и контуров объектов. Иерархия классов относительно класса СРеn пред-
ставлена на рисунке.

CObject

CGdiObject

CPen

Конструкторы класса СРеn


В классе СРеn определены три конструктора, прототипы которых приведены ниже. Первый конст-
руктор позволяет создавать объекты, не связанные с объектами Windows.
CPen ();
Второй конструктор предназначен для создания объектов класса с одновременным созданием ка-
рандашей Windows.
CPen ( int nPenStyle , int nWidth , COLORREF crColor ) ;
Параметры:
nPenStyle определяет стиль пера. Этот параметр может принимать одно из следующих значений:
PS_SOLID сплошная линия.
PS_NULL прозрачная линия.
PS_INSIDEFRAME сплошная линия для рисования по внутренней границе замкнутой области
PS_DASH длинные штрихи.
PS_DOT короткие штрихи.
PS_DASHDOT штрих-пунктир.
PS_DASHDOTDOT штрих-пунктир-пунктир.
Значение последних четырёх флагов действительно, если ширина пера nWidth больше 1. В этом
случае используется флаг PS_SOLID.
nWidth определяет ширину пера. Если это значение составляет 0, то ширина пера равна 1.
crColor определяет цвет пера.
Пример: создаём синий карандаш толщиной 3 единицы, который рисует сплошную линию.

Выжол Ю.А.
Лекция 14 Работа с графикой 12
CPen penBlue ( PS_SOLID , 3 , RGB ( 0 , 0 , 255 )) ;
Третья версия конструктора предназначена для создания объектов класса с одновременным созда-
нием карандашей Windows.
CPen ( int nPenStyle, int nWidth , const LOGBRUSH* pLogBrush , int nStyleCount = 0 , const DWORD*
lpStyle = NULL );

Создание карандаша. Функция CreatePen


Если при создании объекта “карандаш” использован первый конструктор, то определить его пара-
метры можно с помощью функции CreatePen. Функция CreatePen создает логический карандаш, которая
имеет указанный стиль, ширину и цвет. Прототип этой функции имеет следующий вид:
HPEN CreatePen ( int nPenStyle , int nWidth , COLORREF crColor ) ;
Возвращаемое значение: указатель на карандаш, если функция успешно выполнена, и недействитель-
ное значение NULL в противном случае.
Параметры: те же, что и у второго конструктора класса CPen.
Пример: создаём красный карандаш толщиной 1 единица, который рисует линию из длинных штрихов.
CPen penRed ;
penRed.CreatePen ( PS_DASH , 0 , RGB ( 255 , 0 , 0 )) ;
Для каждой переменой типа CPen функция CreatePen может быть вызвана только один раз, т.е. па-
раметры экземпляра класса карандаша нельзя изменить в ходе программы, но можно создать несколько
карандашей и пользоваться ими по очереди.

Создание указателя на карандаш. Тип HPEN


В библиотеке MFC определён тип указателя на карандаш HPEN. Функция CreatePen может быть
также использована для инициализации указателя на карандаш, который удобно использовать при работе
с графикой.
Пример: создаём указатель на синий карандаш толщиной 3 единицы, который рисует сплошную линию.
HPEN hPenBlue = CreatePen ( PS_SOLID , 3 , RGB ( 0 , 0 , 255 )) ;

Использование объекта. Функция SelectObject


Контекст устройства содержит несколько объектов (карандаш, кисть, шрифт, растровую картинку и
область отсечения) с параметрами, заданными по умолчанию. Карандаш, например, по умолчанию чёр-
ный сплошной единичной толщины. Чтобы использовать созданный нами карандаш необходимо передать
его параметры контексту устройства.
Для этой цели в классе CDC определено пять версий функции SelectObject, передающие контексту
устройства адрес объекта, который мы хотим использовать при создании изображения. Прототипы версий
этой функции имеют следующий вид:
CPen* SelectObject ( CPen* pPen ) ; // передаёт адрес карандаша
CBrush* SelectObject ( CBrush* pBrush ) ; // передаёт адрес кисти
virtual CFont* SelectObject ( CFont* pFont ) ; // передаёт адрес фонта
CBitmap* SelectObject ( CBitmap* pBitmap ) ; // передаёт адрес растровой картинки
int SelectObject ( CRgn* pRgn ) ; // передаёт параметры области отсечения
Параметры:
pPen указатель на объект типа CPen (карандаш), который выбран для использования.
pBrush указатель на объект типа CBrush (кисть), который выбран для использования.
pFont указатель на объект типа CFont (фонт), который выбран для использования.
pBitmap указатель на объект типа CBitmap (растровая картинка), который выбран для
использования.
pRgn указатель на объект типа CRgn (область отсечения), который выбран для использова-
ния.
Пример: рисуем прямоугольник в текущем диалоговом окне с помощью определённого нами карандаша.
CClientDC dc ( this ) ; // контекст устройства – текущее диалоговое окно
CPen penRed ( PS_SOLID , 2 , 255 ) ; // создаём сплошной красный карандаш
dc.SelectObject ( &penRed ) ; // выбираем карандаш для использования
RECT rt = { 20 , 20 , 40 , 40 } ; // объявляем и инициализируем прямоугольник

Выжол Ю.А.
Лекция 14 Работа с графикой 13
dc.Rectangle ( &rt ) ; // рисуем прямоугольник

Получение атрибутов объекта. Функция GetObject


В некоторых случаях, например, если графический объект содержит много атрибутов, удобно не
создавать объект, а получить текущий и изменить некоторые его свойства. Для этой цели в классе
CGdiObject определена функция GetObject, синтаксис которой имеет вид:
int GetObject ( int nCount , LPVOID lpObject ) const ;
Функция возвращает количество скопированных байтов или ноль, если произошла ошибка.
Параметры:
lpObject указатель на буфер, который получает информацию;
nCount определяет количество байтов для копирования в буфер lpObject.
Функция заполняет буфер данными, которые определяют указанный объект. Тип буфера определя-
ется видом графического объекта в соответствии со следующим списком:
Тип объекта Тип буфера
CPen LOGPEN
CBrush LOGBRUSH
CFont LOGFONT
CBitmap BITMAP
CPalette WORD
CRgn Не поддерживается

НАСТРОЙКА РЕЖИМА ОТОБРАЖЕНИЯ


Все функциями вывода используют координаты заданные в логических единицах. По умолчанию в
качестве логических координат используются физические координаты текущего окна. Физические коорди-
наты – это расстояние точки от верхнего левого угла окна в пикселях. При этом начало координат (точка
x = 0, y = 0 ) располагается в верхнем левом углу, x-координата растёт слева направо, а y-координата –
сверху вниз.
Если при создании изображения использовать логические координаты, то такие задачи, как пропор-
циональное изменение размеров или перемещение изображения можно элементарно решить с помощью
изменения единиц измерения или перемещения системы координат, не изменяя написанного кода.
Функции из этой группы устанавливают и настраивают систему координат, которая используется
всеми функциями вывода. Кроме единиц по осям x и у, функции этой группы задают направление осей и
начало координат.

Выбор единиц измерения. Функция SetMapMode


Назначение: устанавливает направление осей и определяет логические единицы, т.е. единицы измере-
ния для задаваемой системы координат.
virtual int SetMapMode ( int nMapMode ) ;
Возвращаемое значение: предыдущее значение режима преобразования логических координат в физи-
ческие.
Параметры:
nMapMode определяет новый режим преобразования логических координат в физические. Может
принимать одно из следующих значений:
MM_TEXT логическая единица равна одному пикселю, ось у направлена вниз (режим
по умолчанию)
MM_TWIPS логическая единица равна 1 твипу), ось у направлена вверх (20 твипов = 1
типографскому пункту, 1440 твипов = 1 дюйму
MM_HIENGLISH логическая единица равна 0.001 дюйма, ось у направлена вверх
MM_HIMETRIC логическая единица равна 0.01 миллиметра, ось у направлена вверх
MM_LOENGLISH логическая единица равна 0.01 дюйма, ось у направлена вверх
MM_LOMETRIC логическая единица равна 0.1 миллиметра, ось у направлена вверх
MM_ISOTROPIC режим позволяет настраивать с помощью функций SetWindowExt и Set-
ViewportExt размерность осей и их направления, однако размерность оси х
равна размерности оси у

Выжол Ю.А.
Лекция 14 Работа с графикой 14
MM_ANISOTROPIC режим позволяет настраивать с помощью функций SetWindowExt и Set-
ViewportExt размерность осей координат и их направления (отдельно для
каждой)

Задание произвольных единиц измерения. Функции SetViewportExt и SetWindowExt


Для настройки размеров физической области вывода используются функции:
virtual CSize SetViewportExt ( int cx , int cy ) ;
virtual CSize SetViewportExt ( SIZE size ) ;
Для настройки размеров логической области вывода используются функции:
virtual CSize SetWindowExt ( int cx , int cy ) ;
virtual CSize SetWindowExt ( SIZE size ) ;
Все четыре функции в качестве параметров получают новые значения – размеры по осям, а возвра-
щают прежние. Эти значения используются для преобразования логических координат в физические. При
этом коэффициентом пересчёта является отношение соответствующих размеров. Настройка размеров для
физического окна вывода позволяет управлять направлением осей. Для изменения направления, напри-
мер, оси у, размер должен быть задан с отрицательным значением.

Размер прямоугольника. Структура SIZE


Структура SIZE определяет размер прямоугольника и объявлена в библиотеке MFC следующим
образом:
typedef struct tagSIZE
{
LONG cx; // ширина прямоугольника
LONG cy; // высота прямоугольника
} SIZE, *PSIZE;
В библиотеке MFC определён также класс CSize, который подобен структуре SIZE.
Этот класс происходит от структуры SIZE. Это означает, что вы можете передавать объект типа
CSize в качестве параметра функции типа SIZE и наоборот.

Настройка начала координат. Функции SetViewportOrg и SetWindowOrg


По умолчанию начало координат логической области располагается в верхнем левом углу текущего
контекста. Изменить положение начала координат отображаемой логической области можно одним из
способов: либо переместить начало координат в указанную точку контекста, либо определить точку логи-
ческой области, которая будет отображаться в верхнем левом углу физической области вывода.
Для настройки начала координат физической области вывода используются функции:
virtual CPoint SetViewportOrg ( int x , int y ) ;
virtual CPoint SetViewportOrg ( POINT point ) ;
В качестве параметров указываются координаты физической области, которые в дальнейшем будут
являться началом координат.
Для настройки начала координат логической области вывода используются функции:
CPoint SetWindowOrg ( int x , int у ) ;
CPoint SetWindowOrg ( POINT point ) ;
В качестве параметров указываются координаты логической области, которые в дальнейшем будут
соответствовать левому верхнему углу логической области вывода.
Все четыре функции в качестве параметров получают новые значения для установки начала коорди-
нат и возвращают прежние.
Получить значения для установки начала координат можно с помощью функций:
CPoint GetViewportOrg ( ) const ;
CPoint GetWindowOrg ( ) const ;

Получение размеров клиентской области. Функция GetClientRect


Клиентской областью называется вся площадь диалогового окна или элемента управления за ис-
ключением его границы. Рисунок может располагаться во всей клиентской области. Поэтому при форми-
ровании рисунка необходимо знать её размеры. Для получения размеров клиентской области можно ис-

Выжол Ю.А.
Лекция 14 Работа с графикой 15
пользовать функцию GetClientRect, которая определена в классе CWnd и у всех его потомков соответст-
венно. Функция копирует координаты клиентской области в структуру, на которую указывает параметр.
void GetClientRect ( LPRECT lpRect ) const ;
lpRect указатель на структуру типа RECT или объект типа CRect. После вызова функции поля
left и top будут равны 0, а поля right и bottom будут содержать ширину и высоту окна в
пикселях.

Пример настройки режима отображения


В приведённом ниже примере рисуются оси координат, их подписи и прямоугольник. Рисунок фор-
мируется с использованием фиксированных координат в логической области постоянного размера. Рису-
нок выводится в диалоговом окне, размер которого пользователь может изменить произвольным образом.
Сформированный рисунок всегда отображается в центре формы. Размер рисунка пропорционален разме-
ру формы.
При написании кода нам не пришлось выполнять пересчёт логических координат в физические ко-
ординаты по достаточно простым, но громоздким формулам. Функцию масштабирования рисунка берёт на
себя класс CDC, а нам достаточно передать ему необходимые параметры с помощью описанных выше
функций.
void CMapeModeDlg::OnPicture()
{
const n = 1000 ; // размер логической области
RECT rtWin ; // прямоугольник клиентской области
// создаём совместимый контекст устройства и связываем его с текущим окном
CClientDC dc ( this ) ;
// получаем параметры клиентской области в пикселях
GetClientRect ( &rtWin ) ;
// переносим начало координат в середину физической области
dc.SetViewportOrg ( rtWin.right / 2 , rtWin.bottom / 2 ) ;
// устанавливаем флаг произвольной шкалы, как по оси X, так и по оси Y
dc.SetMapMode ( MM_ANISOTROPIC ) ;
// устанавливаем размеры логической области
dc.SetWindowExt ( n , n ) ;
// устанавливаем размеры физической области равными размерам клиентской области
// и изменяем направление оси Y
dc.SetViewportExt ( rtWin.right , -rtWin.bottom ) ;
dc.Rectangle ( 300 , 300 , -200 , -200 ) ; // рисуем прямоугольник
// рисуем оси координат
CPen penBlack ( PS_SOLID , 5 , RGB(0,0,0)) ; // объявляем сплошной чёрный карандаш
dc.SelectObject ( &penBlack ) ; // выбираем карандаш для использования
dc.MoveTo (-400 , 0 ) ; dc.LineTo ( 400 , 0 ) ; // рисуем ось X
dc.MoveTo ( 0 ,-400 ) ; dc.LineTo ( 0 , 400 ) ; // рисуем ось Y
// рисуем подписи осей координат
COLORREF cr = dc.GetPixel (-499 , 499 ) ; // определяем цвет фона окна
dc.SetBkColor ( cr ) ; // устанавливаем цвет фона текста
dc.TextOut (410 , 25 ,"X") ; // рисуем подпись оси X
dc.TextOut (-10 , 450 ,"Y") ; // рисуем подпись оси Y
}
Приведенный код выполняется в классе CMapeModeDlg при щелчке на кнопке IDC_PICTURE
В результате работы этого фрагмента кода в форме будет выведен следующий рисунок.

Выжол Ю.А.
Лекция 14 Работа с графикой 16

КИСТЬ. КЛАСС CBRUSH


Иерархия классов относительно класса СРеn представлена на рисунке. Класс СРеn инкапсулирует
графический объект Windows – “кисть”. Кисть используется для закрашивания замкнутых фигур.

CObject

CGdiObject

CBrush

Конструкторы класса CBrush


В классе CBrush определено четыре конструктора, прототипы которых имеют вид:
CBrush ( ) ; // создает пустой объект
CBrush ( COLORREF crColor ) ; // создает однотонную кисть
CBrush ( int nIndex , COLORREF crColor ) ; // создает кисть со штриховкой
CBrush ( CBitmap* pBitmap ) ; // создает кисть на основе битового массива размером 8x8
Параметры:
crColor определяет цвет штрихов
nIndex определяет стиль штриховки. Может принимать одно из следующих значений:
HS_HORIZONTAL горизонтальная штриховка
HS_VERTICAL вертикальная штриховка
HS_BDIAGONAL 45-градусная штриховка слева направо и сверху вниз
HS_FDIAGONAL 45-градусная штриховка слева направо и снизу вверх
HS_CROSS горизонтальная и вертикальная штриховка крест-накрест
HS_DIAGCROSS 45-градусная штриховка крест-накрест
pBitmap указатель на объект типа CBitmap, который определяет точечный рисунок, ис-
пользуемый в качестве шаблона
В том случае если создана кисть со штрихами, то в качестве цвета фона используется цвет фона
текста, который задаётся с помощью функции SetBkColor.
Пример: рисуем прямоугольник в текущем диалоговом окне с помощью определённой нами кисти.
CClientDC dc ( this ) ; // контекст устройства - текущее диалоговое окно
COLORREF crYell = 0xFFFF ; // объявляем жёлтый цвет для фона
COLORREF crBlue = 0xFF0000 ; // объявляем синий цвет для штрихов
CBrush brush ( HS_CROSS , crBlue ) ; // объявляем кисть со штриховкой крест-накрест
dc.SetBkColor ( crYell ) ; // устанавливаем жёлтый фон
dc.SelectObject ( brush ) ; // выбираем кисть для использования
RECT rt = { 20 , 20 , 140 , 140 } ; // объявляем и инициализируем прямоугольник
dc.Rectangle ( &rt ) ; // рисуем прямоугольник

Образец физической кисти. Структура LOGBRUSH


Структура LOGBRUSH определяет стиль, цвет, и образец физической кисти и объявлена в библио-
теке MFC следующим образом:
typedef struct tag LOGBRUSH
{
UINT lbStyle ; // стиль кисти

Выжол Ю.А.
Лекция 14 Работа с графикой 17
COLORREF lbColor ; // цвет кисти
LONG lbHatch ; // тип штриховки или указатель на точечный рисунок
} LOGBRUSH ;
Члены структуры:
lbStyle определяет стиль кисти и должен принимать одно из следующих значений:
BS_HOLLOW пустая кисть
BS_NULL пустая кисть
BS_HATCHED штрихуемая кисть
BS_SOLID сплошная кисть
BS_PATTERN в качестве кисти используется точечный рисунок
lbColor определяет цвет кисти, если поле lbStyle равно BS_HATCHED или BS_SOLID;
игнорируется, если поле lbStyle равно BS_HOLLOW или BS_PATTERN.
lbHatch определяет тип штриховки, если поле lbStyle равно BS_HATCHED. В этом случае поле
может принимать те же значения, что и параметр nIndex в конструкторе класса CBrush.
Структура LOGBRUSH используется функциями CreateBrushIndirect и ExtCreatePen.

Создание кисти
Если кисть создана с помощью первого конструктора и является пустым объектом, то перед исполь-
зованием его необходимо проинициализировать с помощью одной из следующих функций:
BOOL CreateSolidBrush ( COLORREF crColor ) ;
Функция создает однотонную кисть с заданным цветом.
BOOL CreateHatchBrush ( int nIndex , COLORREF crColor ) ;
Функция создает кисть со штриховкой заданного цвета и направления.
BOOL CreatePatternBrush ( CBitmap* pBitmap ) ;
Функция создает кисть на основе битового массива размером 8x8.
BOOL CreateBrushIndirect ( const LOGBRUSH* lpLogBrush ) ;
Функция создаёт кисть, используя двухцветный (1 бит на пиксель) точечный рисунок. Пиксели, пред-
ставленные нулём рисуются текущим цветом текста. Пиксели, представленные единицей рисуются теку-
щим цветом фона. Кроме того, может создавать однотонную кисть и кисть со штриховкой.
BOOL CreateDIBPatternBrush ( HGLOBAL hPackedDIB , UINT nUsage ) ;
BOOL CreateDIBPatternBrush ( const void* lpPackedDIB , UINT nUsage ) ;
Функция создает кисть на основе битового массива, который хранит изображение в независимом от
устройства виде (Device-Independent Bitmap – DIB).
BOOL CreateSysColorBrush ( int nIndex ) ;
Функция создает кисть со штриховкой на основе системного цвета.

Пример создания и использования кисти


В приведённом ниже примере мы создаём образец физической кисти, по образцу создаём кисть и
рисуем прямоугольник в текущем диалоговом окне с помощью созданной нами кисти.
CClientDC dc ( this ) ; // контекст устройства – текущее диалоговое окно
LOGBRUSH logBr ; // объявляем образец физической кисти
logBrush.lbStyle = BS_HATCHED ; // устанавливаем стиль штрихованной кисти
logBrush.lbColor = RGB ( 0 , 192 , 192 ) ; // устанавливаем цвет штрихов
logBrush.lbHatch = HS_DIAGCROSS ; // штриховка крест-накрест по диагонали
CBrush brush ; // объявляем пустую кисть
brush.CreateBrushIndirect ( &logBr ) ; // создаём кисть по образцу
dc.SelectObject ( brush ) ; // выбираем кисть для использования
dc.Rectangle ( 20 , 20 , 100 , 100 ) ; // рисуем прямоугольник

Выжол Ю.А.
Лекция 14 Работа с графикой 18
ТОЧЕЧНЫЙ РИСУНОК. КЛАСС CBITMAP
Класс CBitmap инкапсулирует графический объект Windows – “точечный рисунок”. Точечный рису-
нок – это прямоугольная матрица целых чисел, каждое из которых кодирует цвет пикселя в прямоугольной
области. Точечный рисунок используется при создании кисти, может отображаться в форме или элементе
управления. Иерархия классов относительно класса CBitmap представлена на рисунке.

CObject

CGdiObject

CBitmap

Создание точечного рисунка. Функция CreateBitmap


Для работы с объектом класса необходимо объявить сам объект, а затем инициализировать его с
помощью одной из следующих функций: CreateBitmap, CreateBitmapIndirect, CreateCompatibleBitmap,
CreateDiscardableBitmap.
Синтаксис функции CreateBitmap имеет вид:
BOOL CreateBitmap ( int nWidth, int nHeight, UINT nPlanes, UINT nBitCount, const void* lpBits ) ;
Параметры:
nWidth, nHeight определяет ширину и высоту точечного рисунка в пикселях.
nPlanes определяет число цветов в точечном рисунке.
nBitCount определяет число битов за пиксель.
lpBits указатель на массив коротких целых чисел, который содержит разрядные значе-
ния точечного рисунка. Если параметр недействителен, то новый точечный рису-
нок оставлен без инициализации.
В том случае если пиксель кодируется одним битом (nBitCount = 1), то пиксель которому соответст-
вует значение бита равное 1 закрашивается цветом фона, 0 – цветом текста. Цвет фона и текста можно
установить с помощью функций SetBkColor и SetTextColor соответственно.
Пример: В приведённом ниже примере объявлен и проинициализирован массив bit , состоящий из 8 це-
лых чисел типа WORD. Каждое число кодирует 8 пикселей одной из 8 строк. На базе массива bit с помо-
щью функции CreateBitmap создаётся точечный рисунок bm размером 8 x 8. В точечный рисунке крайний
правый и самый нижний ряды пикселей имеют цвет текста, остальные пиксели – цвет фона. Далее созда-
ётся кисть brush, которая использует созданный точечный рисунок bm. Кисть brush используется при ри-
совании прямоугольника.
CClientDC dc ( this ) ; // контекст устройства - текущее диалоговое окно
WORD p = 0xFE ; // двоичный код = 11111110
WORD bit [ 8 ] = {p,p,p,p,p,p,p,0} ; // массив из 8 битовых строк
dc.SetBkColor ( dc.GetPixel ( 0 , 0 )) ; // устанавливаем цвет фона равным цвету фона окна
CBitmap bm ; // объявляем точечный рисунок
bm.CreateBitmap ( 8 , 8 , 1 , 1 , bit ) ; // инициализируем точечный рисунок размером 8 x 8
CBrush brush ; // объявляем пустую кисть
brush.CreatePatternBrush ( &bm ) ; // создаём на основе точечного рисунка
dc.SelectObject ( brush ) ; // выбираем кисть для использования
dc.Rectangle ( 23 , 23 , 89 , 89 ) ; // рисуем закрашенный прямоугольник

Создание ресурса точечного рисунка


Интегрированная среда разработки Visual Studio 6 позволяет создавать точечные рисунки с помо-
щью встроенного графического редактора. Для этого нужно
в меню Insert выбрать команду Resource
в диалоговом окне Insert Resource в поле Resource type выбрать Bitmap и нажать кнопку New

Выжол Ю.А.
Лекция 14 Работа с графикой 19

Встроенный графический редактор позволяет создавать 256-цветные рисунки произвольного разме-


ра. При создании рисунка пользователю доступны команды рисования простейших примитивов с помощью
мыши: точки, прямой, эллипса, прямоугольника и др.
Библиотека MFC позволяет использовать в программе готовые точечные рисунки, содержащие и
более чем 256 цветов. Для включения готового точечного рисунка в проект нужно
в диалоговом окне Insert Resource нажать кнопку Import
в диалоговом окне открытия файла выбрать файл и нажать кнопку Import
Ресурс типа Bitmap, как и любой другой ресурс, в откомпилированной программе хранится в испол-
няемом файле, но загружается в оперативную память только после выполнения соответствующей коман-
ды загрузки ресурса. Ресурс выгружается из оперативной памяти, если он не требуется для выполнения
программы.

Загрузка ресурса точечного рисунка. Функция LoadBitmap


Загрузить ресурс точечного рисунка можно с помощью функции LoadBitmap.
BOOL LoadBitmap ( UINT nIDResource ) ;
BOOL LoadBitmap ( LPCTSTR lpszResourceName ) ;
Параметром функции может быть идентификатор ресурса nIDResource или строка. содержащая
имя идентификатора ресурса lpszResourceName.
Загруженный точечный рисунок присоединен к объекту типа CBitmap.
Пример: В приведённом ниже примере точечный рисунок загружается из ресурса с идентификатором
IDB_BIT.
CBitmap bm ; // объявляем точечный рисунок
bm.LoadBitmap ( IDB_BIT ) ; // загружаем точечный рисунок из ресурса с IDB_BIT

Выжол Ю.А.

Вам также может понравиться