Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ISVP_Labs_16_17.doc
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
8 Мб
Скачать
☆

6.Графика в WinForms (cli)

Я всегда мечтал о том, чтобы моим компьютером можно было пользоваться так же легко, как телефоном. Моя мечта сбылась: я уже не могу разобраться, как пользоваться моим телефоном

Bjarne Stroustrup

Цель работы – освоить разработку приложений Windows на основе каркаса WinForms на языке C++/CLI, которые используют графические средства WinForms. Кроме того, вы научитесь создавать и использовать контекстное меню и таймер (4 час.).

6.1.Задание

Разработайте приложение на основе каркаса Windows Forms, которое бы иллюстрировало использование графических возможностей этой платформы. Для этого выполните упражнения из подраздела 5.2, а затем – индивидуальные задания из подраздела 5.3.

6.2.Бесценные методические предписания

Шаг 1. Создаем проект. Как и в предыдущей работе, выберите каркас приложения в соответствии с рис. 1: выберите Visual C++ в левой панели и Windows Forms Application – в правой. Тем самым мы получим возможность использовать язык C++/CLI для программирования. Настоятельно рекомендую не устанавливать переключатель «Create directory for solution». В данном сценарии я нарек проект оригинальным именем WFGraph.

Рис. 1. Выбор каркаса приложения

Шаг 2. Простейший способ рисования. Класс формы имеет много событий, одним из которых является событие (event) Paint, которое возникает всякий раз при необходимости обновления содержимого окна. Для создания обработчика этого события выберите в окне редактирования ресурс окно (имя вкладки Form1.h[Design]), выделите ЛКМ собственно окно, вызовите его свойства и в этом окне щелкните по иконке Events. В появившемся списке найдите имя события Paint и сделайте по нему двойной щелчок ЛКМ. В результате этих героических усилий у вас появится обработчик Form1_Paint. Доведите его до такого, например, состояния:

Запустив приложение на выполнение, попробуйте изменять размеры окна и понаблюдайте за эллипсом, чтобы он никуда не сбежал.

Шаг 3. Рисование вне обработчика Form1_Paint. Это можно делать элементарно двумя способами. Первый из них состоит в том, что можно в функции Form1_Paint можно вызвать любую другую функцию и передать в нее дескриптор System::Windows::Forms::PaintEventArgs в качестве фактического параметра, например:

System::Void Form1_Paint(System::Object^ sender,

System::Windows::Forms::PaintEventArgs^ e)

{

DrawExample(e);

}

/* Нарисуем еще один эллипс путем изменения положения

прямоугольника, в который вписывается эллипс*/

rect.X=180;/*"Сдвинули" эллипс вправо по оси Х*/

rect.Y=20;/*"Сдвинули" эллипс вниз по оси Y*/

/* Другой способ задания цвета пера - через его ARGB-составляющие

с помощью метода FromArgb(Int32, Int32, Int32, Int32),

например:*/

myPen = gcnew Pen(Color::FromArgb(255, 123, 23, 3),2.0f );

e->Graphics->DrawEllipse( myPen, rect );

/* Создаем кисть для закрашивания эллипса*/

SolidBrush^ redBrush=gcnew SolidBrush(Color::Red);

e->Graphics->FillEllipse(redBrush, rect.X, rect.Y, rect.Width,

rect.Height);

/* Можно получить составляющие цвета по его имени и вывести

их в окно формы:*/

Color slateBlue = Color::FromName( "SlateBlue");

/* Выделяем составляющие цвета*/

Byte g = slateBlue.G;

Byte b = slateBlue.B;

Byte r = slateBlue.R;

Byte a = slateBlue.A;

/* Помещаем их в массив ради прикола*/

array<Object^> ^temp0 = {a,r,g,b};

/* Формируем строку символов для вывода в окно*/

String^ text = String::Format( "Составляющие цвета SlateBlue:

" Alpha:{0}, red:{1}, green: {2}, blue {3}", temp0 );

/* Выводим текст в окно*/

e->Graphics->DrawString( text, gcnew System::Drawing::Font(

this->Font,FontStyle::Bold ),

gcnew SolidBrush(slateBlue), RectangleF(PointF(0.0F,120.0F),

this->Size) );

}

Проанализируйте текст функции, в котором показаны некоторые средства и приемы рисования. Результат выполнения функции приведен на рис. 2.

Рис. 2. Рисуем яйца

Второй способ рисования состоит в создании дескриптора объекта Graphics и использовании его функций для рисования. Вызовите эту функцию в обработчике Form1_Paint – и наслаждайтесь.

Проанализируйте текст следующей функции:

Шаг 4. Рисование в управляющем элементе PictureBox. Можно рисовать не только непосредственно в окне формы, но и в управляющих элементах, как, например, в приведенной ниже функции DrawInPictureBox(). Для того чтобы эта функция «работала», разместите на форме управляющий элемент PictureBox и не переживайте по поводу его размеров и положения, так как они задаются в коде функции DrawInPictureBox(). Если ваш элемент будет иметь имя pictureBox1, измените его на pictureBox3 или измените его имя в функции. Достоинством такого подхода – рисования в управляющем элементе – является тот факт, что для перемещения рисунка достаточно просто перемещать управляющий элемент.

Шаг 5. Загрузка изображения в управляющий элементе PictureBox. На этапе дизайна делается элементарно. Разместите на форме элемент PictureBox, определитесь с его положением и размерами. Вызовите для элемента его свойства, найдите свойство Image, щелкните кнопку выбора изображения и загрузите файл с требуемым изображением. После загрузки это изображение будет сохранено в файле приложения Form1.resX и исходный файл уже не нужен. Скорее всего, вам захочется выбрать для свойства SizeMode значение StretchImage, которое обеспечит «автоматическое» растяжение изображения на всю площадь управляющего элемента PictureBox.

Это изображение можно также преспокойненько загрузить на этапе выполнения программы, например, как это делает наглая хвункция DrawImageRunTime():

Если вдруг эта функция не компилируется – добавьте на форму элемент pictureBox2 и ни в чем себе не отказывайте. Попробуйте, опять-таки, изменять размеры окна приложения: что происходит с загруженным изображением 9AIST-sky.JPG?

Рис. 3. Файлы 9AIST-sky.JPG и RingP.JPG

Шаг 6. Перемещение изображения. Создайте в любом графическом редакторе изображение закрашенной окружности, то бишь круга, и сохраните его в файле, например, RingP.JPG (см. рис.3).Пусть на форме имеется элемент pictureBox4. Загрузите в него изображение RingP.JPG. Свойству SizeMode элемента pictureBox4 присвойте значение StretchImage. Теперь напишем функцию, которая будет перемещать элемент pictureBox4 в заданную позицию клиентской области окна (x,y).

/*ShowRing - изменяет позицию pictureBox4 на экране, вследствие

чего изображение перемещается в окне форме*/

System::Void ShowRing(int x, int y)

{

this->pictureBox4->Location = System::Drawing::Point(x,y);

}

Как видите, перемещение изображения круга реализуется э-л-е-м-е-н-т-а-р-н-о. А как сделать так, чтобы круг летал по экрану или как шарик отскакивал от краев клиентской области окна? Щас зробімо.

Шаг 7. Создаем контекстное меню. Для инициирования и перемещения некоторого изображения по экрану в соответствии с некоторым алгоритмом можно использовать разные приемы. В качестве инициатора перемещения удобно использовать таймер, который с заданной периодичностью будет выполнять некоторые действия. В то же время требуется иметь средство, которое будет запускать таймер и его останавливать. В качестве такого средства можно использовать команды меню, обработчики шлепков по кнопкам, нажатия клавиш, истошные вопли и т.д. Мы для этой цели, в качестве тренажа, используем контекстное меню, то бишь управляющий элемент ContextMenuStrip из группы Menus & Toolbars.

Итак, затащите на форму упомянутый элемент ContextMenuStrip и бросьте его там. Когда он свалится с окна вниз, выделите его там, внизу, и далее с помощью интуитивно понятных действий добавьте в него две команды: Start и Stop. Не рекомендую вводить имена кириллицей на этапе создания команд меню, так как вы получите имена команд и их обработчиков, в которых будут присутствовать эти самые символы кириллицы. Когда вы создадите команды меню, вызовите их свойства и в поле Text введите имена команд кириллицей или на любом другом доступном языке.

Далее привычным двойным щелчком по ЛКМ сгенерируйте обработчики этих самых команд меню. Как известно, контекстное меню вызывается по умолчанию путем нажатия ПКМ в окне. Запустите приложение на выполнение и щелкните ПКМ в окне. Выскочило меню? Если нет, то доберитесь до свойств окна, найдите там свойство ContextMenuStrip и выпадающем списке выберите имя contextMenuStrip1. Еще раз запустите приложение на выполнение и убедитесь в том, что контекстное меню выскакивает как черт из коробочки.

Шаг 8. А теперь – таймер и полетели! Отыщите в ToolBox элемент Timer (группа Components) и каким-нибудь хитрым способом заманите его на форму. Он с нее, конечно, сбежит, но вы его найдите и хорошенько шлепните, чтобы он родил обработчик события timer1_Tick. Если вы посмотрите на свойства таймера timer1, то обнаружите там свойство Interval. Значение этого свойства задает промежуток времени в миллисекундах, через который будет вызываться обработчик timer1_Tick. Таймер начнет «работать», когда будет вызван его метод Start (не путать с командой нашего контекстного меню!) и закончит свою работу, когда будет вызван метод Stop.

Итак, в самой дебильной реализации обработчики событий можно сделать такими:

System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e)

{

static int x=200, y=200; // А зачем static, а если его убрать?

ShowRing(x++,y--);

}

System::Void startToolStripMenuItem_Click(System::Object^ sender,

System::EventArgs^ e)

{

timer1->Interval=100;

timer1->Start();

}

System::Void stopToolStripMenuItem_Click(System::Object^ sender,

System::EventArgs^ e)

{

timer1->Stop();

}

Если теперь запустить программу на выполнение, вызвать контекстное меню (ПКМ) и выбрать команду Старт, то шарик должен начать двигаться вверх и вправо. Остановить его можно с помощью команды Стоп контекстного меню.

Поздравляю, вот теперь вы готовы к выполнению настоящего задания!

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