- •Интерактивные графические системы
- •Лабораторная работа 1-2.
- •Создание программ построения графиков, используя графические примитивы api Windows. Создание меню, для отображения различных графических объектов
- •Содержание
- •Мировые и экранные координаты.
- •Графические библиотеки.
- •Программирование графики в Windows.
- •Контекст устройства
- •Получить контекст устройства
- •Контекст устройства в Windows программах.
- •Аналогичную схему создания и уничтожения пера можно представить в виде.
- •Графические примитивы api Windows.
- •Шрифты True Type в Windows программах.
- •Обработка сообщений меню Windows программы
- •Задание к выполнению лабораторной работы.
- •Часть 1. Написать Windows программу для своего варианта, которая рисует сразу два графика в одних координатных осях.
Контекст устройства
Если наша программа создает графическое изображение, то это изображение не сразу попадает на устройство вывода. Устройством вывода может быть экран монитора, принтер, графопостроитель, метафайл и т.д. Связь между приложением и устройством вывода можно изобразить в виде схемы.
Программа
|
Контекст устройства
|
Драйвер устройства
|
Устройство вывода
Разберем что такое контекст устройства. С формальной точки зрения контекст устройства – это структура данных. Каждый контекст устройства связан со своим устройством вывода.
Нас будет интересовать контекст устройства связанный с видеодисплеем. В контексте устройства хранится набор атрибутов рисунка и графические инструменты, заданные по умолчанию. Пользователь может использовать заданные по умолчанию атрибуты и инструменты, а также может изменять их сам.
Графическими инструментами являются перья и кисти разной толщины, стиля и цвета.
Часто контекст устройства образно сравнивают с абстрактным листом бумаги или поверхностью, на которой приложение рисует графическое изображение или пишет текст. Далее контекст устройства через драйвер связывается со своим физическим устройством вывода, на котором уже появляется реальное изображение.
Разберем подробно, как пользоваться контекстом устройства. Покажем на схеме шесть основных шагов для рисования графики.
Получить контекст устройства
|
Установить атрибуты рисунка
|
Создать и выбрать графические инструменты
|
Вызвать функции рисования
|
Освободить и уничтожить графические инструменты
|
Освободить контекст устройства
Использование контекста устройства в DOS и Windows имеет отличия.
Пример программы построения графика в Windows.
Теперь возьмем за
основу проект OnlyWin,
и внесем изменения так,
что бы в полученном окне можно было
нарисовать график функции
.
Пусть новый проект называетсяGraphWin.
Файл OnlyWin.cpp
переделаем в файл GraphWin.cpp,
внеся небольшие изменения в код программы.
Во-первых, нужны две дополнительные библиотеки стандартного языка C++.
#include <math.h>
#include <stdio.h>
#include <tchar.h>
Во-вторых, необходимо объявить функцию Line_OnPaint(), которая будет рисовать график. Поэтому вначале программы надо добавить прототип этой функции.
//прототипы функций
void Line_OnPaint(HWND);
В-третьих, для вызова функции Line_OnPaint() будем использовать сообщение WM_PAINT . Поэтому надо добавить несколько строчек кода в функцию окна WndProc.
switch(message)
{
case WM_PAINT:
Line_OnPaint(hWnd);
break;
}
В-четвертых, необходимо определить функцию Line_OnPaint(), которая будет рисовать график. Приведем определение функции Line_OnPaint().
//размеры окна вывода в мировой системе координат
double xLeft, xRight, yBottom, yTop;
//размеры окна вывода в пикселях на экране монитора
int nLeft, nRight, mBottom, mTop;
//переход от x к пикселю n
inline int xn(double x)
{
return (int)((x - xLeft)/(xRight - xLeft)*(nRight - nLeft)) + nLeft;
}
//переход от y к пикселю m
inline int ym(double y)
{
return (int)((y - yBottom)/(yTop - yBottom)*(mTop - mBottom)) + mBottom;
}
//функция обрабатывающая сообщение WM_PAINT
void Line_OnPaint(HWND hwnd)
{
//размеры окна в мировых координатах и в пикселях
xLeft = -2; xRight = 10; yBottom = -2; yTop = 2;
nLeft = 100; nRight = 450; mBottom = 350; mTop = 50;
//создаем массивы точек для аргумента x и функции y = sin(x)
const int N = 50;
double corX[N], corY[N];
double x, y, dx = (xRight - xLeft)/(N-1);
for(int i=0; i<N; i++)
{
x = xLeft + dx*i; y = sin(x);
corX[i] = x; corY[i] = y;
}
HDC hdc; //идентификатор контекста устройства
PAINTSTRUCT ps; //структура для работы контекста
//получаем контекст устройства <hdc> для окна <hwnd>
hdc = BeginPaint(hwnd, &ps);
HBRUSH hbrush, hbrushOld; //идентификаторы кистей
HPEN hpen1, hpen2, hpen3, hpenOld; //идентификаторы перьев
//создаем кисть <hbrush>, стиль - сплошной, цвет - синий
hbrush = CreateSolidBrush(RGB(0, 0, 200));
//выбираем кисть <hbrush> в контекст устройства <hdc>,
//запоминаем идентификтор старой кисти <hbrushOld>
hbrushOld = (HBRUSH)SelectObject(hdc,hbrush);
//создаем перо <hpen1>
//, стиль - сплошной, толщина 3 пиксела, цвет - ярко-желтый
hpen1 = CreatePen(PS_SOLID, 3, RGB(255, 255, 0));
//выбираем перо <hpen1> в контекст устройства <hdc>,
//запоминаем идентификтор старого пера <hpenOld>
hpenOld = (HPEN)SelectObject(hdc, hpen1);
Rectangle(hdc, nLeft, mBottom, nRight, mTop);
//создаем перо <hpen2>
// стиль - сплошной, толщина 1 пиксел, цвет - ярко-голубой
hpen2 = CreatePen(PS_SOLID, 1, RGB(0, 255, 255));
//выбираем перо <hpen2> в контекст устройства <hdc>
SelectObject(hdc, hpen2);
int nb, ne, mb, me;
POINT pt;
//рисуем ось OX
nb = xn(xLeft); mb = ym(0);
MoveToEx(hdc, nb, mb, &pt);
ne = xn(xRight); me = ym(0);
LineTo(hdc, ne, me);
//рисуем ось OY
nb = xn(0); mb = ym(yBottom);
MoveToEx(hdc, nb, mb, &pt);
ne = xn(0); me = ym(yTop);
LineTo(hdc, ne, me);
//название графика и осей
SetTextColor(hdc, RGB(255, 255, 255));
SetBkColor(hdc, RGB(127, 127, 127));
TextOut(hdc, nLeft-35, (mBottom+mTop)/2, _T("Y"), 1);
TextOut(hdc, (nLeft+nRight)/2, mBottom+25, _T("X"), 1);
//выводим числа вдоль осей
TCHAR ss[10];
swprintf_s(ss,10, L"%6.1lf", xLeft);
TextOut(hdc, nLeft-30, mBottom+7, ss, 6);
swprintf_s(ss,10, L"%6.1lf", xRight);
TextOut(hdc, nRight-30, mBottom+7, ss, 6);
swprintf_s(ss,10, L"%6.1lf", yBottom);
TextOut(hdc, nLeft-55, mBottom-7, ss, 6);
swprintf_s(ss,10, L"%6.1lf", yTop);
TextOut(hdc, nLeft-55, mTop+3, ss, 6);
//рисуем график по двум массивам
//создаем перо <hpen3>,
// стиль - сплошной, толщина 2 пиксел, цвет - ярко-красный
hpen3 = CreatePen(PS_SOLID, 2, RGB(255, 0, 0));
//выбираем перо <hpen3> в контекст устройства <hdc>
SelectObject(hdc, hpen3);
nb = xn(corX[0]); mb = ym(corY[0]);
MoveToEx(hdc, nb, mb, &pt);
for( i=1; i<N; i++)
{
nb = xn(corX[i]); mb = ym(corY[i]);
LineTo(hdc, nb, mb);
}
//выбираем старую кисть <hbrushOld> в контекст устройства <hdc>
SelectObject(hdc, hbrushOld);
DeleteObject(hbrush); //уничтожаем кисть <hbrush>
//выбираем старое перо <hpenOld> в контекст устройства <hdc>
SelectObject(hdc, hpenOld);
DeleteObject(hpen1); //уничтожаем перо <hpen1>
DeleteObject(hpen2); //уничтожаем перо <hpen2>
DeleteObject(hpen3); //уничтожаем перо <hpen3>
//освобождаем контекст устройства <hdc> в окне <hwnd>
EndPaint(hwnd, &ps);
}

Рис.7
Результат работы программы GraphWin.exe.
Далее обычным образом компилируем и создаем исполняемый файл GraphWin.exe. Запускаем программу на выполнение. Результат показан на Рис. 7.
На примере функции Line_OnPaint() рассмотрим применение контекста устройства в программах работающих под Windows.
