Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
321-352.doc
Скачиваний:
6
Добавлен:
11.11.2019
Размер:
521.73 Кб
Скачать

Задание 1. Создание объектов контекста устройства, инструментов рисования и демонстрация режимов отображения

Рассмотрим программу, выполняющую демонстрацию особенностей режимов отображения координат MM_TEXT и MM_HIMETRIC. В этом задании мы дополним программу MyPaint кодом, который отображает в главном окне программы линии в качестве координатных осей с разметкой их в соответствии с различными режимами отображения. В результате работы программы вы получите изображения, такие как на рис. 10.4 и 10.5. Для добавления в программу новых функциональных возможностей выполните следующие действия:

  1. Скопируйте проект MyPaint в новый каталог и откройте его

  2. Откройте окно редактора меню для внесения в него изменений.

Рис. 10.7. Меню программы MyPaint после добавления команды Graphics

  1. Добавьте новый пункт меню, введя в него надпись &Graphics. Перейдите к следующему свободному полю под командой Graphics и ведите надпись &Mode (Режим). Для пункта меню Mode создайте всплывающее меню c надписями MM_TEXT и MM_HIMETRIC. Расположите созданный пункт меню Graphics перед пунктом Help, переместив его по панели меню. Вы получите такое меню, как показано на рис. 10.7. Идентификаторы новых пунктов меню создал редактор ресурсов меню. Для упрощения идентификации ресурсов замените предложенные редактором идентификаторы команд, указав значения ID_MODE_MMTEXT и ID_MODE_MMHIMETRIC. Для изменения значения идентификаторов используйте окно Properties и поле ID в нем или контекстное меню и его команду Edit IDs.

  2. Добавьте обработчики сообщений, генерируемых выбором добавленных команд меню. Для этого выполните команду Add Event Handler…. В диалоговом окне Event Handler Wizard в поле Message type выберите тип сообщения COMMAND, в поле Class list выберите класс CMainFrame для добавления в него создаваемого обработчика сообщений. В поле Function handler name уже указано имя функции OnModeMmtext. Нажмите кнопку Add and Edit для завершения работы с мастером создания обработчиков сообщений. Для того, чтобы не менять сценарий работы программы графического редактора, разработку которого мы закончим на этом занятии, в качестве класса для демонстрации особенностей режима отображения и графических примитивов выбран класс CMainFrame главного окна-рамки.

  3. Повторите действия, описанные в пункте 4 этого упражнения для добавления обработчиков сообщений от команд меню MM_HIMETRIC. Вы получите объявление новых функций в классе CMainFrame главного окна-рамки в файле MainFrm.h. В файле реализации класса главного окна-рамки MainFrm.cpp появятся шаблоны функций, в карте реализации — макросы ON_COMMAND():

// MainFrm.h : interface of the CMainFrame class class CMainFrame : public CFrameWnd { protected: // create from serialization only CMainFrame(); DECLARE_DYNCREATE(CMainFrame) //не приводятся объявления стандартных и добавленных ранее //функций public: afx_msg void OnModeMmtext(); afx_msg void OnModeMmhimetric(); };

// MainFrm.cpp : implementation of the CMainFrame class BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_WM_CREATE() ON_COMMAND(ID_MODE_MMTEXT, OnModeMmtext) ON_COMMAND(ID_MODE_MMHIMETRIC, OnModeMmhimetric) END_MESSAGE_MAP()

  1. Для демонстрации единиц измерения и направлений изменения значений координат по горизонтали и вертикали в окне представления добавьте следующие переменные в класс CMainFrame: x, y типа int для определения текущих координат точки, scalex, scaley типа int для вычисления масштабов по осям Х и Y. Выполните команду ProjectAdd Variable…. В диалоговом окне Add Member Variable Wizard заполните поля Variable type и Variable name и нажмите кнопку Finish. В интерфейс класса CMainFrame добавятся объявления переменных , а в конструктор класса — их инициализация.

public: //текущие координаты точки int x; int y; int scalex; //масштаб по оси Х int scaley; //масштаб по оси Y

  1. Реализуйте обработчик сообщений, генерируемый при выборе команды GraphicsModeMM_TEXT, чтобы получить такое изображение, как на рис. 10.4. Для этого добавьте еще одну функцию-член класса CMainFrame, с помощью которой очистится экран от дополнительных линий, ограничивающих движение курсора при рисовании по командам меню Lines. Для добавления функции-члена класса выполните команду меню ProjectAdd Function…. для класса CMainFrame. В диалоговом окне Add Member Function Wizard в поле Return type выберите тип void. В поле Parameter type введите void или оставьте поле пустым, в поле Function name введите имя функции ClearClient. Остальные поля не заполняйте и нажмите кнопку Finish для окончания работы с мастером. В файл интерфейса класса CMainFrame добавится объявление функции. Поскольку функция не является обработчиком сообщений, то в карту сообщений дополнительные макросы не добавятся.

public: void ClearClient();

  1. Добавьте код в функцию CMainFrame::ClearClient(), который определит объекты контекста устройства и кисти, инициализирует кисть белым цветом, выберет объект кисти в объекте контекста устройства, определит размер клиентской области окна, отобразит прямоугольник такого размера, как размер области окна и выполнит заливку этого прямоугольника белым цветом. В результате будет создана иллюзия очистки окна. Добавленный код приводится ниже полужирным шрифтом. При определении координат вершин прямоугольника учтены размеры в пикселах горизонтальной и вертикальной полос прокрутки, строки состояния и панели инструментов. Значения, передаваемые в функции, подобраны экспериментальным путем.

void CMainFrame::ClearClient() //Очищает рабочее пространство { CClientDC dc(this); CBrush ClearBrush; ClearBrush.CreateSolidBrush(RGB(255,255,255)); SetBkMode((HDC)(COLOR_WINDOW+1),NULL); dc.SelectObject(&ClearBrush); CRect rect; GetClientRect(rect); dc.Rectangle(0,26,(rect.right-rect.left)-20, (rect.bottom-rect.top)-35); }

  1. Добавьте код в функцию CMainFrame::OnModeMmtext(), которая обрабатывает сообщение от команды меню GraphicsModeMM_TEXT. В добавленном коде определите объект контекста устройства и размер клиентской области окна, создайте объект перо, инициализируйте и выберите его в объекте контекста устройства, сохраните указатель на предыдущий объект перо. Затем вычислите масштабы по горизонтальной и вертикальной осям, задайте режим отображения MM_TEXT, отобразите горизонтальную линию (30 пикселов занимает полоса прокрутки) и вертикальную линию (60 пикселов занимает полоса прокрутки и строка состояния), а также выведите надписи на осях. Выполните разметку осей, отображая на них вертикальные и горизонтальные линии длиной в 10 пикселов через промежутки, равные величине масштаба. Наконец, выведите цифровое обозначение шкалы деления. После выполнения рисования отсоедините объект перо от объекта контекста устройства и удалите объект перо.

void CMainFrame::OnModeMmtext() { // TODO: Add your command handler code here ClearClient(); //очистить окно CClientDC dc(this);//определить объект контекста устройства RECT rect; GetClientRect(&rect);//определить размер клиентской части окна CPen newpen; //объявить объект перо CPen* oldpen;//объявить указатель на предыдущий объект перо newpen.CreatePen(PS_SOLID,1,RGB(255,0,255)); //создать перо //выбрать объект перо в объекте контекста устройства oldpen=dc.SelectObject(&newpen); int vertmark=20; //количество вертикальных меток на оси Х int horizmark=20;//количество горизонтальных меток на оси Y scalex = (rect.right-rect.left)/horizmark; scaley = (rect.bottom-rect.top)/vertmark; dc.SetMapMode(MM_TEXT); //задать режим отображения dc.MoveTo(10,30); //перейти в заданную точку //отобразить горизонтальную линию //30 пикселов занимает полоса прокрутки dc.LineTo(rect.right-40,30); dc.TextOut(rect.right-40,30,"X"); //вывести надпись dc.MoveTo(5,rect.top+30); //отобразить вертикальную линию //60 пикселов занимает полоса прокрутки и строка состояния dc.LineTo(5,rect.bottom-60); dc.TextOut(5,rect.bottom-60,"Y"); CString str; //объект для преобразования в строку y=30; //отступ на величину панели инструментов for(int i=0; i<=rect.right; i++) //выполнить разметку оси X { x=i*scalex; str.Format("%d",i*scalex); dc.MoveTo(x,y); dc.LineTo(x,y+10); if(x!=0) //исключить отображение символа '0' dc.TextOut(x,y+15,str); } //выполнить разметку оси Y x=5; //отступ вправо от рамки окна for(int j=rect.top+30;j<=rect.bottom-30;j++) { //учитывать сдвиг на высоту панели инструментов y=(j-30)*scaley; str.Format("%d",y); y+=30; dc.MoveTo(x,y); //построение шкалы делений на оси Y dc.LineTo(x+10,y); if (y!=30) dc.TextOut(x+15,y,str); } //отсоединить объект перо от объекта контекста устройства dc.SelectObject(oldpen); newpen.DeleteObject(); //удалить объект перо }

  1. Постройте и запустите программу по команде DebugStart. Если во время компиляции вы получите сообщение о повторном определении значения MM_TEXT, то необходимо открыть в редакторе Notepad файл определения ресурсов resource.h и удалить строку, показанную ниже:

#define MM_TEXT 100

  1. Повторите построение программы. При тестировании программы MyPaint выполните команду GraphicsModeMM_TEXT. Вы увидите на экране дисплея главное окно с изображением осей и их разметки (рис. 10.4). Обратите внимание на то, что мы не запрограммировали обновление окна при его перекрытии, прокрутке и изменении размеров.

  2. Добаьте код в функцию CMainFrame::OnModeMmhimetric(), которая обрабатывает сообщение от команды меню GraphicsModeMM_HIMETRIC. В этой функции необходимо выполнить такие же операции, что и в CMainFrame::OnModeMmtext(). Отличие заключается в правилах вычисления текущих координат точки. Необходимо помнить, что единицей измерения в режиме MM_HIMETRIC является не один пиксел, как в режиме MM_TEXT, а 0,01мм, координаты по оси Х возрастают слева направо, а по оси Y — снизу вверх. Кроме того, по умолчанию система координат окна располагается в правом нижнем квадранте общепринятой декартовой системы координат. Поэтому в режиме MM_HIMETRIC появляются отрицательные значения координат. Для демонстрации режима рисования вызовите функцию СDC::SetROP2() с аргументом R2_NOTCOPYPEN для инвертирования цвета пера. Можете использовать любое другое значение аргумента с целью изучения возможностей установки атрибутов рисования. Добавленный код представлен полужирным шрифтом.

void CMainFrame::OnModeMmhimetric() { // TODO: Add your command handler code here ClearClient(); //очистить окно CClientDC dc(this);//определить объект контекста устройства RECT rect; GetClientRect(&rect);//определить размер клиентской части CPen newpen; //объявить объект перо CPen* oldpen; //объявить указатель на предыдущий объект перо newpen.CreatePen(PS_SOLID,1,RGB(0,255,0)); //создать перо //выбрать объект перо в объекте контекста устройства oldpen=dc.SelectObject(&newpen); int vertmark=20; //количество вертикальных меток на оси Х int horizmark=20;//количество горизонтальных меток на оси Y scalex=(int)(rect.right-rect.left)/horizmark; scaley=(int)(rect.bottom-rect.top)/vertmark; dc.SetMapMode(MM_HIMETRIC); //выбрать режим отображения dc.SetROP2(R2_NOTCOPYPEN); //выбрать режим рисования //ось X dc.MoveTo(100,rect.top-1000); dc.LineTo(rect.right*30-100,rect.top-1000); dc.TextOut(rect.right*30-500,rect.top-1500,"X"); //ось Y dc.MoveTo(100,-1000); dc.LineTo(100,-rect.bottom*27); dc.TextOut(100,-rect.bottom*27,"-Y"); //разметка оси Х CString str;//временный объект для преобразования типов y=-rect.top-1000; for(int i=0; i<=rect.right; i++) { x=i*scalex/0.01; dc.MoveTo(x,y); //построение шкалы делений на оси х dc.LineTo(x,y-500); //запретить выводить цифры по оси Х на полосе прокрутке if(x>0&&x<rect.right*30-i*1.6*100) { str.Format("%d",x); dc.TextOut(x,y-800,str); } } //разметка оси Y x=100; //отступ от левого края окна для проведения оси Y for(int j=0; j>=-rect.bottom;j--) { y=j*scaley/0.01; //построение шкалы делений на оси Y dc.MoveTo(x,y); dc.LineTo(x+300,y); if(y!=0&&y>-rect.bottom*27) { str.Format("%d",y); dc.TextOut(x+500,y,str); } } }

  1. Постройте и запустите программу по команде DebugStart. При тестировании программы MyPaint выполните команду GraphicsModeMM_HIMETRIC.

Вы увидите на экране дисплея главное окно с изображением осей и их разметки (рис. 10.5).

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]