ЛАБОРАТОРНАЯ РАБОТА №5.
ДЕЛЕГАТЫ, СОБЫТИЯ. DRAG&DROP.
Цель
Познакомится с событиями и делегатами. Ознакомиться с работой механизма drag&drop.
Задание
Используя механизм Drag&Drop выбирать тип отрисовываемого объекта и его цвет. Реализовать это все на отдельной форме с вызовом этой формы из основной формы. Передачу сформированного объекта в главную форму осуществлять, используя события. Использовать анонимные функции при решении задачи.
Продолжим тематику машин. Сделаем парковку автосалона, который будем заполнять машинами по желаниям заказчиков (тут в качестве желания будет выступать цвет машины). Нам понадобится 2 формы. Одна будет отображать парковку, вторая – выбор машины и ее настройки.
Разберемся сначала со второй формой. В этой форме потребуется следующий функционал: выбор типа машины и выбор цветов (только основной или еще дополнительный для спортивных машин).
Добавим pictureBox для отображения машины. Добавим groupBox куда добавим 2 Label с вариантами выбора машин, которые мы можем сделать (обычная машина или спорт-версия). Сделаем красивый выбор кузова путем «перетаскивания» элементов. Для этого воспользуемся технологией Drag&Drop.
Для выполнения операций перетаскивания в приложениях Windows необходимо обрабатывать последовательность событий, главным образом события DragEnter, DragLeave и DragDrop. Перетаскивание можно с легкостью организовать при работе со сведениями, доступными через аргументы этих событий.
Рассмотрим это сразу на примере. Начнем с Label с надписью «Car». Все операции перетаскивания начинаются с переноса данных. Функциональные возможности, позволяющие собрать данные при начале перетаскивания, реализуются в методе DoDragDrop. Как и где это применять?. Все начинается, когда мы нажимаем кнопкой мыши на объекте, который хотим перетащить. У каждого элемента формы есть событие, которое срабатывает при нажатии кнопки мыши на него, называется MouseDown. Найдем у Label это событие.
В методе-обработки этого события и будем вызывать метод DoDragDrop для нашего Label, в котором сообщим, что мы будем передавать.
Первым параметром, передаваемым в этот метод, является объект, который будет перемещаться. В нашем случае, это будет строка с текстом, размещенным в Label’е. Вторым параметром – возможные результаты операции перетаскивания. В нашем случае это будут операции перемещения и копирования. Результаты можно комбинировать, используя логические операторы.
Теперь на получателе нужно оформить 2 метода, для приема. Но тут возникает проблема. На элементе, который будет принимать перетаскиваемый объект, должно быть свойство AllowDrop. Но его нет у элемента pictureBox. Поэтому сделаем хитрость, поместим pictureBox в panel. У panel задаем значение свойства AllowDrop значением true.
И задаем методы для 2-х событий: DragEnter и DragDrop.
Событие DragEnter позволяет убедиться в корректности происходящих действий, в нашем случае, это должен быть текст (строка).
Событие DragDrop будет основным, в нем будет реализовываться основная логика. Логика заключается в следующем: в зависимости от переданного текста создать либо обычную машину, либо спортивную версию. Цвет зададим по умолчанию: кузов белый, доп. цвет полосок для спортивных машин – черный. Также, создадим метод, который будет отрисовывать созданную машину. Для этого переменную car сделаем полем класса-формы.
Теперь займемся цветами. Зададим 8 возможных цветов. Для разнообразия для этого на форме зададим 8 маленьких панелей, каждую из которых раскрасим в определенный цвет, используя у панелей свойство BackColor. На панели, на которой находится наш pictureBox зададим 2 Label’а, один, куда мы будем перетаскивать цвет для основного кузова, второй, для дополнительного цвета.
Чтобы менять цвета у машины, придется дополнить наши интерфейс ITransport методом получения нового базового цвета и определить его в абстрактном классе Vehicle. А для класса SportCar определить еще метод для получения дополнительного цвета.
Для Label основного цвета зададим DragEnter и DragDrop. В качестве передаваемого параметра будет цвет.
Теперь нам надо определить для каждой панели метод MouseDown. Получается 8 раз!! Можно это как-то упростить? По идее, мы задали нужный цвет в свойстве BackColor каждой из панелей. Нам, по сути, надо создать универсальный метод для всех панелей, который бы брал у выбранной панели ее свойство BackColor и передавал в метод DoDragDrop. Теперь проблема, как узнать какую панель выбрали? Но здесь все просто. В каждый вызываемый метод ,как правило, передается 2 параметра: второй – это вызываемое событие, а первый – объект, который его вызвал. Вот он и будет нам нужен. Нам даже все равно что это будет, панель или что-то иное, главное, чтобы он относился к классу элементов формы (класс Control).
Все, остается этот метод назначить всем панелям. Либо делаем на форме через свойства каждой панели, либо прописываем это в коде, например в конструкторе класса:
Все тоже самое нужно проделать для доп. цвета. При этом, так как методы DragEnter будут идентичные, можем воспользоваться методом DragEnter для основного цвета и определить только метод DragDrop для доп цвета.
Чтобы видеть, куда мы перетаскиваем, зададим свойство BorderStyle у всех элементов равным FixedSingle, чтобы видеть их границы. У Label свойство AutoSize поставить равным false, чтобы задать нужные размеры для элементов.
Кинем на форму еще 2 кнопки «Добавить» и «Отмена».
На отмену будет простой код: закрытие формы. Сделаем его через анонимную функцию.
Воспользуемся нашими классами для отрисовки парковки из предыдущей лабораторной. За одно возьмем оттуда форму отрисовки парковки Уберем кнопки выбора добавления машины и добавим одну кнопку, которая будет вызывать другую форму.
Теперь как можно вызвать одну форму из другой? Для этого в классе первой формы создаем объект от второй формы.
Теперь в методе обработки нажатия кнопки «Добавить» инициализируем объект от формы и вызываем у объекта метод Show() иди ShowDialog() для вызова формы. Первый вызывает вторую форму, не блокируя первую. А второй метод блокирует первую форму, пока не закроется вторая.
При выборе первого варианта возникает проблема. После закрытия второй формы, мы должны получить от нее информацию о выбранной машине и добавит ее в гараж. Но как это сделать, если мы не знаем когда закроется эта форма? Со вторым вариантом все просто:
Выполнение кода метода продолжится после строки form.ShowDialog(); только когда закроется форма. А для первого варианта придется создать делегат, от него во второй форме событие, функцию добавления к событию метода, и первой форме функцию, которая будет навязываться событию.
Для простоты прям в файле Programm.cs создадим делегат
Затем, во второй форме – событие. И метод добавления к этому событию методов. И вызов события при нажатии кнопки «Добавить»
И в первой форме навязываем событие и создаем метод для этого события.
Все, теперь сработает и первый вариант вызова формы.
Код первой формы:
public partial class FormSelectCar : Form
{
/// <summary>
/// Переменная-выбранная машина
/// </summary>
ITransport car = null;
/// <summary>
/// Получить машину
/// </summary>
public ITransport getCar { get { return car; } }
/// <summary>
/// Отрисовать машину
/// </summary>
private void DrawCar()
{
if (car != null)
{
Bitmap bmp = new Bitmap(pictureBoxCar.Width, pictureBoxCar.Height);
Graphics gr = Graphics.FromImage(bmp);
car.setPosition(5, 5);
car.drawCar(gr);
pictureBoxCar.Image = bmp;
}
}
/// <summary>
/// Событие
/// </summary>
private event myDel eventAddCar;
/// <summary>
/// Добавление события
/// </summary>
/// <param name="ev"></param>
public void AddEvent(myDel ev)
{
if (eventAddCar == null)
{
eventAddCar = new myDel(ev);
}
else
{
eventAddCar += ev;
}
}
public FormSelectCar()
{
InitializeComponent();
panelBlack.MouseDown += panelColor_MouseDown;
panelGold.MouseDown += panelColor_MouseDown;
panelGray.MouseDown += panelColor_MouseDown;
panelGreen.MouseDown += panelColor_MouseDown;
panelRed.MouseDown += panelColor_MouseDown;
panelWhite.MouseDown += panelColor_MouseDown;
panelYellow.MouseDown += panelColor_MouseDown;
panelBlue.MouseDown += panelColor_MouseDown;
buttonCancel.Click += (object sender, EventArgs e) => { Close(); };
}
/// <summary>
/// Готовимся к перетаскиванию
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void labelCar_MouseDown(object sender, MouseEventArgs e)
{
labelCar.DoDragDrop(labelCar.Text,
DragDropEffects.Move | DragDropEffects.Copy);
}
/// <summary>
/// Готовимся к перетаскиванию
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void labelSportSedan_MouseDown(object sender, MouseEventArgs e)
{
labelSportCar.DoDragDrop(labelSportCar.Text, DragDropEffects.Move | DragDropEffects.Copy);
}
/// <summary>
/// Проверяем, что мы принимаем (мы не всеядные)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void panelCar_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.Text))
e.Effect = DragDropEffects.Copy;
else
e.Effect = DragDropEffects.None;
}
/// <summary>
/// Принимаем то, что перетаскивали
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void panelCar_DragDrop(object sender, DragEventArgs e)
{
switch (e.Data.GetData(DataFormats.Text).ToString())
{//случаным образом выбриаем какая машина встанет
case "Car":
car = new Car(100, 4, 500, Color.White);
break;
case "SportCar":
car = new SportCar(100, 4, 500, Color.White, true, true, true, Color.Black);
break;
}
DrawCar();
}
/// <summary>
/// Перетаскиваем цвет с панели
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void panelColor_MouseDown(object sender, MouseEventArgs e)
{
(sender as Control).DoDragDrop((sender as Control).BackColor,
DragDropEffects.Move | DragDropEffects.Copy);
}
/// <summary>
/// Готовимся к приему
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void labelBaseColor_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(Color)))
e.Effect = DragDropEffects.Copy;
else
e.Effect = DragDropEffects.None;
}
/// <summary>
/// Принимаем
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void labelBaseColor_DragDrop(object sender, DragEventArgs e)
{
if (car != null)
{
car.setMainColor((Color)e.Data.GetData(typeof(Color)));
DrawCar();
}
}
/// <summary>
/// Принимаем
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void labelDopColor_DragDrop(object sender, DragEventArgs e)
{
if (car != null)
{
if (car is SportCar)
{
(car as SportCar).setDopColor((Color)e.Data.GetData(typeof(Color)));
DrawCar();
}
}
}
/// <summary>
/// Добавление машины
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonOk_Click(object sender, EventArgs e)
{
if (eventAddCar != null)
{
eventAddCar(car);
}
Close();
}
}
Код второй формы:
public partial class FormParking : Form
{
/// <summary>
/// Парковка
/// </summary>
Parking parking;
/// <summary>
/// Форма для добавления
/// </summary>
FormSelectCar form;
public FormParking()
{
InitializeComponent();
parking = new Parking(5);
//заполнение listBox
for (int i = 1; i < 6; i++)
{
listBoxLevels.Items.Add("Уровень " + i);
}
listBoxLevels.SelectedIndex = parking.getCurrentLevel;
Draw();
}
/// <summary>
/// Метод для отрисовки уровня парковки
/// </summary>
private void Draw()
{
if (listBoxLevels.SelectedIndex > -1)
{//если выбран один из пуктов в listBox (при старте программы ни один пункт не будет выбран и может возникнуть ошибка, если мы попытаемся обратиться к элементу listBox)
Bitmap bmp = new Bitmap(pictureBoxParking.Width, pictureBoxParking.Height);
Graphics gr = Graphics.FromImage(bmp);
parking.Draw(gr);
pictureBoxParking.Image = bmp;
}
}
/// <summary>
/// Перемещаемся на следующий уровень парковки
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonDown_Click(object sender, EventArgs e)
{
parking.LevelDown();
listBoxLevels.SelectedIndex = parking.getCurrentLevel;
Draw();
}
/// <summary>
/// Перемещаемся на нижний уровень парковки
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonUp_Click(object sender, EventArgs e)
{
parking.LevelUp();
listBoxLevels.SelectedIndex = parking.getCurrentLevel;
Draw();
}
/// <summary>
/// Вызываем форму добавления машины
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonSetCar_Click(object sender, EventArgs e)
{
form = new FormSelectCar();
form.AddEvent(AddCar);
form.Show();
}
/// <summary>
/// Метод добавления машины
/// </summary>
/// <param name="car"></param>
private void AddCar(ITransport car)
{
if (car != null)
{
int place = parking.PutCarInParking(car);
if (place > -1)
{
Draw();
MessageBox.Show("Ваше место: " + place);
}
else
{
MessageBox.Show("Машину не удалось поставить");
}
}
}
/// <summary>
/// Ставим гоночную машину
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonSetSportCar_Click(object sender, EventArgs e)
{
ColorDialog dialog = new ColorDialog();
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
ColorDialog dialogDop = new ColorDialog();
if (dialogDop.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
var car = new SportCar(100, 4, 1000, dialog.Color, true, true, true, dialogDop.Color);
int place = parking.PutCarInParking(car);
Draw();
MessageBox.Show("Ваше место: " + place);
}
}
}
/// <summary>
/// Забираем машину
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonTakeCar_Click(object sender, EventArgs e)
{
if (listBoxLevels.SelectedIndex > -1)
{//Прежде чем забрать машину, надо выбрать с какого уровня будем забирать
string level = listBoxLevels.Items[listBoxLevels.SelectedIndex].ToString();
if (maskedTextBox1.Text != "")
{
ITransport car = parking.GetCarInParking(Convert.ToInt32(maskedTextBox1.Text));
if (car != null)
{//если удалось забрать, то отрисовываем
Bitmap bmp = new Bitmap(pictureBoxTakeCar.Width, pictureBoxTakeCar.Height);
Graphics gr = Graphics.FromImage(bmp);
car.setPosition(5, 5);
car.drawCar(gr);
pictureBoxTakeCar.Image = bmp;
Draw();
}
else
{//иначе сообщаем об этом
MessageBox.Show("Извинте, на этом месте нет машины");
}
}
}
}
}
Варианты:
1. Тигровая Акула – Океан
2. Электровоз – Депо
3. Грузовик – Парковка/Дорога
4. Бомбардировщик – Аэродром/Небо
5. Теплоход – Океан/Причал
6. Бубен – Магазин
7. Линкор – Океан/Причал
8. Горбатый кит - Океан
9. Катер – Океан/Причал
10. Тепловоз – Депо
11. Парусник – Океан/Причал
12. Истребитель – Аэродром/Небо
13. Саксофон – Магазин
14. Автобус – Парковка/Дорога
15. Летающая тарелка – Аэродром/Небо
16. Амурский тигр – Зоопарк/Земля
17. Бриллиант – Магазин
18. Аэробус – Аэродром/Небо
19. Кобра – Террариум/Земля
20. Танк – Гараж/Поле битвы
21. Гитара – Магазин
22. Серый кролик – Зоопарк/Земля
23. Внедорожник – Парковка/Дорога
24. Легкий самолет – Аэродром/Небо
25. Аллигатор – Река/Аквариум
26. БТР – Гараж/Поле битвы
27. Катамаран – Океан/Причал
28. Круизный лайнер – Океан/Причал
29. Тарантул – Террариум/Земля
30. Крейсер – Океан/Причал
Похожие материалы
... и оперативного управления процессом обучения, что в свою очередь снижает морально-психологическое напряжение, испытываемое слушателем (студентом) в период сессии. Преимущества и достоинства системы дистанционного обучения, базирующейся на современных телекоммуникационных средствах, становятся очевидными, когда большая часть рутинных операций технологии организации учебного процесса проводятся в ...
0 комментариев