У вас вопросы?
У нас ответы:) SamZan.net

Лабораторная работа 3

Работа добавлена на сайт samzan.net:

Поможем написать учебную работу

Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.

Предоплата всего

от 25%

Подписываем

договор

Выберите тип работы:

Скидка 25% при заказе до 28.12.2024

Лабораторная работа №3.

Знакомство с графическими компонентами MS Visual C++

Цель работы:

Понять принципы разработки графических приложений в среде Visual C++. Познакомиться со свойствами и методами соответствующих классов.

Задание

Разработать графический редактор. Редактор должен обеспечить выполнение следующих действий:

  1.   рисование в интерактивном режиме трех простейших примитивов: линии,   прямоугольника и эллипса. Соответственно в форме должны быть 3 кнопки с изображением этих фигур. После выбора кнопки контуры фигуры на экране создаются при помощи мыши
  2.   выбор цвета границ фигуры и толщины линии
  3.   заливка замкнутой области выбранным цветом
  4.   запись изображения в файл .bmp и чтение из файла

Указания по выполнению работы.

Сконструируем основное меню редактора с пунктами Файл (Создать, Открыть, Сохранить, Сохранить как, Выход), Карандаш (цвет, толщина), Кисть (цвет), используя компонент menuStrip - главное меню.

Поместим на форму компоненты-диалоги: два сolorDialog для выбора цвета карандаша и кисти; openFileDialog и saveFileDialog для открытия и сохранения файлов. Задайте для двух последних фильтр (свойство Filter) на графические типы файлов:

Image Files(*.BMP;*.JPG;*.PNG)|*.BMP;*.JPG;*.PNG.

Создадим панель с кнопками для удобства выбора изображаемых фигур. Панель – это компонент Panel со страницы Containers. Чтобы она автоматически располагалась вверху формы, задайте для неё свойство Dock в значение Top. Кнопки – обычные компоненты Button. Чтобы изобразить на них рисунки, воспользуемся свойством Image,

которое позволяет выбрать графический файл для рисунка на кнопке. Можно воспользоваться существующими файлами ellipse.bmp, line.bmp, rect.bmp, а в случае их отсутствия – создать свои (например, с помощью редактора Paint).

Для обеспечения возможности изображения фигур на экране и записи изображения в графический файл потребуется компонент pictureBox со страницы Common Controls. Задайте для него свойство Dock равным Fill, чтобы он автоматически растянулся и заполнил всё оставшееся свободное пространство формы.

Компонент pictureBox содержит свойство Image, которое является ссылкой на объект (если быть уж совсем точным, то дескриптором отслеживания в терминологии CLR, но для простоты будем в дальнейшем использовать слово «ссылка»). Класс Image содержит статический метод FromFile(), который создаёт новый объект Image из указанного графического файла и возвращает ссылку на него. Для сохранения же изображения в файл можно использовать метод Save(). Таким образом, для пунктов меню «Открыть» и «Сохранить как» обработчики  будут выглядеть следующим образом:

//Обработчик меню "Открыть"

private: System::Void открытьToolStripMenuItem_Click(System::Object^  sender,

 System::EventArgs^  e)

{  

 if ( openFileDialog1->ShowDialog() ==  System::Windows::Forms::DialogResult::OK ) {   

  if (pictureBox1->Image != nullptr) pictureBox1->Image->~Image();

   pictureBox1->Image = System::Drawing::Image::FromFile(openFileDialog1->FileName);

   Text = openFileDialog1->FileName;

 }

}

//Обработчик меню "Сохранить как"

private: System::Void сохранитьКакToolStripMenuItem_Click(System::Object^  sender,   

 System::EventArgs^  e)

{

 if ( saveFileDialog1->ShowDialog() ==  System::Windows::Forms::DialogResult::OK ){

   pictureBox1->Image->Save(saveFileDialog1->FileName);   

   Text = saveFileDialog1->FileName;   

 }

}

Примечание. В обработчике пункта меню «Открыть» присутствует явный вызов деструктора для объекта Image. Хотя в CLR и имеется такая технология, как сборка мусора (garbage collection), явное уничтожение объектов представляется целесообразным для более быстрого освобождения ресурсов.

Для выбора цвета карандаша в соответствующем обработчике достаточно написать одну строчку:

 penColorDialog->ShowDialog();

Аналогично сделайте и выбор цвета кисти.

 Для рисования простых геометрических фигур используется класс Graphics. Создать объект класса Graphics, связанный с нашим Image, можно с помощью статического метода FromImage(). Вот некоторые методы класса Graphics:

  •  DrawEllipse() – эллипс, FillEllipse() – закрашенный эллипс,
  •  DrawLine() – линия,
  •  DrawRectangle() – прямоугольник, FillRectangle() – закрашенный прямоугольник

Перечисленные методы в качестве первого аргумента требуют объект класса Pen (перо, карандаш) либо Brush (кисть). Вместо самого класса Brush обычно применяются его наследники – SolidBrush (сплошная кисть), TextureBrush (текстурная кисть) и др. Для лучшего понимания приведём пример кода, рисующего закрашенный эллипс и поверх него эллипс-границу другого цвета:

 System::Drawing::Graphics^ g =

   System::Drawing::Graphics::FromImage(pictureBox1->Image);

 System::Drawing::Pen^ pen =

   gcnew System::Drawing::Pen(penColorDialog->Color);

 System::Drawing::Brush^ brush =

   gcnew System::Drawing::SolidBrush(brushColorDialog->Color);

 g->FillEllipse(brush,30,30,20,10);

 g->DrawEllipse(pen,30,30,20,10);

 brush->~Brush();

 pen->~Pen();

 g->~Graphics();

 pictureBox1->Invalidate(); //вызываем перерисовку

Хотя для результирующего приложения данный кусок кода, конечно, не нужен, но попробуйте всё же его вставить в обработчик на какой-нибудь пункт меню и выполнить. Должна обнаружиться интересная ситуация. Если вы вначале с помощью меню «Файл» - «Открыть» загрузите какой-нибудь графический файл, то всё работает нормально. Если же вы запустите обработчик с пустым pictureBox, то программа завершается с ошибкой.

Проблема заключается в том, что по умолчанию свойство Image компонента pictureBox содержит пустую ссылку (nullptr). Поэтому давайте напишем обработчик пункта меню «Создать», в котором создадим новый объект класса Image (точнее, Bitmap – наследника от Image) и ссылку на него поместим в свойство Image:

//обработчик пункта меню "Создать"

private: System::Void создатьToolStripMenuItem_Click

  (System::Object^  sender, System::EventArgs^  e) {

  pictureBox1->Image =

  gcnew System::Drawing::Bitmap(pictureBox1->Size.Width,

                                pictureBox1->Size.Height);

}

Теперь после нажатия на кнопку «Создать» наш предыдущий пример будет отрабатывать нормально.

Осталось самое трудное – сделать рисование выбранной фигуры с помощью мышки. Для этого  нужно написать три обработчика событий от мыши: MouseDown (при нажатии левой кнопки), MouseMove  (перемещение мыши) и MouseUp (при отпускании нажатой ранее кнопки). При нажатии кнопки необходимо запомнить текущие координаты.

При движении мыши необходимо постоянно стирать и рисовать заново выбранную фигуру, чтобы возникло впечатление, что она изменяется в размерах. Для этого необходимо также запоминать текущие координаты, чтобы стирать фигуру, нарисованную при предыдущем перемещении.

Стирание фигуры – очень интересный момент, поскольку при этом необходимо восстанавливать то, что было нарисовано ранее. Для этого применим следующий приём: рисовать фигуру будем обычным образом, а для стирания создадим отдельный карандаш на основе текстурной кисти (TextureBrush). В свою очередь, в конструктор TextureBrush передадим свойство Image из pictureBox. В результате использования такого карандаша точки линии будут рисоваться в соответствии с текстурой кисти, то есть рисунком, который находился в Image ещё до рисования. И ещё один момент. По умолчанию при применении текстурной кисти рисуемое изображение смешивается с уже имеющимся, а нам нужно, чтобы оно рисовалось взамен его. С этой целью нужно изменить свойство CompositingMode объекта Graphics, задав его равным SourceCopy.

Приведём упрощенный пример подобных обработчиков для рисования только лишь эллипсов. Вам нужно будет их доработать, чтобы можно было рисовать любую фигуру.

//координаты мышки в момент нажатия кнопки

static int startX, startY;

//координаты мышки при предыдущем перемещении

static int prevX, prevY;

//ссылки на некоторые объекты,чтобы всё время не пересоздавать

static System::Drawing::Graphics^ g = nullptr;

static System::Drawing::Pen^ pen = nullptr;

static System::Drawing::Pen^ erasePen = nullptr;

static System::Drawing::Brush^ brush = nullptr;

//нажата кнопка мышки - запоминаем координаты

private: System::Void pictureBox1_MouseDown(System::Object^  sender, System::Windows::Forms::MouseEventArgs^  e) {

 startX = prevX = e->X;

 startY = prevY = e->Y;

 g = System::Drawing::Graphics::FromImage(pictureBox1->Image);

 //создаём обычный карандаш

 pen = gcnew System::Drawing::Pen(penColorDialog->Color);

 //создаём очищающий карандаш

 System::Drawing::Brush^ brush = gcnew 

    System::Drawing::TextureBrush(pictureBox1->Image);  

 erasePen = gcnew System::Drawing::Pen(brush);    

 //режим рисования - замена старого изображения

 g->CompositingMode =

  System::Drawing::Drawing2D::CompositingMode::SourceCopy;

}

//перемещение мышки - перерисовываем фигуру

private: System::Void pictureBox1_MouseMove(System::Object^  sender, System::Windows::Forms::MouseEventArgs^  e) {

 if (g==nullptr) return;

 //стираем нарисованное до этого

 g->DrawEllipse(erasePen,startX,startY,prevX-startX,prevY-startY);

 //и рисуем заново

 g->DrawEllipse(pen,startX,startY,e->X-startX,e->Y-startY);

 prevX=e->X; prevY=e->Y;

 pictureBox1->Invalidate(); //вызываем перерисовку

}

//отпускание мышки - освобождаем ресурсы

private: System::Void pictureBox1_MouseUp(System::Object^  sender, System::Windows::Forms::MouseEventArgs^  e) {

 pen->~Pen();  pen=nullptr;

 erasePen->Brush->~Brush();

 erasePen->~Pen();  erasePen=nullptr;  

 g->~Graphics(); g=nullptr;

}

На данный момент редактор должен выглядеть примерно так:

Самостоятельные задания.

  1.  Напишите обработчики для пунктов меню «Сохранить», «Выход». Предусмотрите запрос пользователя о сохранении изменений в тех случаях, где это требуется (см. лабораторную работу по текстовому редактору).
  2.  Сделайте, чтобы при запуске программы автоматически вызывался обработчик для пункта меню «Создать».
  3.  Реализуйте рисование линий и прямоугольников
  4.  Поместите на панель две кнопки для выбора цвета карандаша и цвета кисти (они будут дублировать соответствующие пункты меню). Сделайте так, чтобы эти кнопки были всегда того же цвета, что и выбранный карандаш и кисть.
  5.  Поместите на форму выпадающий список для выбора толщины линии карандаша. Желательно, чтобы в качестве элементов списка показывались не просто слова или числа, а сами линии нужной толщины.
  6.  Поместите на форму переключатель, с помощью которого задаётся, рисовать ли фигуры закрашенными или нет, и реализуйте соответствующую функциональность




1. І. позначає предметність у найширш
2. тема. Учебник под редакцией владимира шамильевича шайхатдинова 2012 особенная часть только
3. ТЕМА 1 Какие клетки из перечисленных относятся к базофильным эндокриноцитам аденогипофиза Хромофо
4. Введение Основными задачами производственной практики являются закрепление и углубление знаний получен
5. тематический план 131018 Разработка и эксплуатация нефтяных и газовых месторожде
6. ТЕМАТИЧЕСКИЙ АНАЛИЗ 3 семестр ГР
7. Стилистические фигуры речи
8.  Учебники 2 Парашкоу С
9. Идвирд Майбридж.html
10. Усі засоби які можуть служити людині для задоволення її потреб називаються благами
11. Организация и тактика тушения пожаров во Дворце искусств
12. МОНОПОЛИСТИЧЕСКАЯ ДЕЯТЕЛЬНОСТЬ НА ТОВАРНОМ РЫНКЕ И ЕЁ ВИДЫ Монополистическая деятельность является прав
13. то тяжёлое. Будь то булава или мечи с щитами опять же деревянные
14.  ТЕОРЕТИЧЕСКИЕ АСПЕКТЫ УЧЕТА НЕМАТЕРИАЛЬНЫХ АКТИВОВ Понятие основных средств К ос
15. Crpthin Forest
16. Искусство Древнего Египта. Древнее царство
17. ВВЕДЕНИЕ При выборе электроизоляционного материала для конкретного применения приходится обращать вни
18. министра принца Раннарита и возобновление в Камбодже вооруженного противостояния правительства и оппозици
19. Средства массовой информации и ребенок
20. Ліквідність банківської системи України