Опубликован: 14.12.2009 | Уровень: для всех | Доступ: платный
Лекция 5:
Программирование в .NET Framework
Пример программы 3.11
Теперь попробуем поиграть с мышкой – работать с графикой удобнее при помощи мыши, а не клавиатуры. Мы будем обрабатывать как растровые, так и векторные изображения, используя некоторые события мыши.
Постараемся освоить некоторые новые действия, а именно — действия с точечными рисунками. Тратить время на подробное описание мы не будем, но небольшое вступление необходимо, чтобы рассказать о принципах работы приведенного ниже кода.
- Компьютерные программы формируют изображение на экране монитора, управляя цветом и яркостью маленьких точек, которые называются пикселями.
- Цвет пикселя определяется тремя цветовыми компонентами: красной (red), зеленой (green) и синей (blue) – в языках программирования часто используется сокращение RGB. Цвет и яркость пикселя можно изменять, регулируя интенсивность компонентов RGB, в пределах от 0 до 255 единиц. Например:
- если red=255, green=0, blue=0 — цвет пикселя будет ярко-красным;
- если red=255, green=255, blue=0 — цвет пикселя желтый.
- Компьютер может отслеживать положение курсора мыши, определяемое координатами X и Y (горизонтальная и вертикальная координаты). Так, верхний левый угол экрана имеет координаты X=0 и Y=0.
using System; using System.Windows.Forms; using System.Drawing; class FunWithTheMouse : Form { // Объявляем объекты, доступные для разных методов PictureBox pictureBox1; Label label1; Point spotClicked; // Метод-конструктор нашего класса public FunWithTheMouse() { // Задаем размеры окна this.Size = new Size(640, 480); // Загружаем рисунок в элемент PictureBox и вставляем в форму pictureBox1 = new PictureBox(); pictureBox1.Image = (Image)new Bitmap(@"../../images/Dog.bmp"); pictureBox1.SizeMode = PictureBoxSizeMode.Normal; pictureBox1.Dock = DockStyle.Fill; this.Controls.Add(pictureBox1); // Добавляем метку с инструкциями в нижнюю часть экрана label1 = new Label(); label1.BackColor = Color.Wheat; label1.Dock = DockStyle.Bottom; label1.Text = "При нажатой левой кнопке мыши можно рисовать прямоугольники. " + "Нажатая правая кнопка изменяет яркость прямоугольника " + "Нажав SHIFT и перемещая мышь, рисуем желтые кружки."; label1.TextAlign = ContentAlignment.MiddleCenter; this.Controls.Add(label1); // Привязываем PictureBox к обработчикам событий мыши this.pictureBox1.MouseDown += new MouseEventHandler(MouseButtonIsDown); this.pictureBox1.MouseUp += new MouseEventHandler(MouseButtonIsUp); this.pictureBox1.MouseMove += new MouseEventHandler(TheMouseMoved); } // Обработчик событий, срабатывающий при ПЕРЕМЕЩЕНИИ мыши public void TheMouseMoved(object sender, MouseEventArgs e) { // Если на клавиатуре нажата клавиша SHIFT if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift) { // Подготовка области рисования на изображении System.Drawing.Graphics g = this.pictureBox1.CreateGraphics(); // Используем желтое перо System.Drawing.Pen yellowPen = new System.Drawing.Pen(Color.Yellow, 3); // Рисуем окружность (эллипс, вписанный в квадрат) // Верхний левый угол квадрата имеет координаты X и Y // текущего положения мыши. g.DrawEllipse(yellowPen, e.X, e.Y, 40, 40); // Очистка g.Dispose(); } } // Обработчик событий, срабатывающий при НАЖАТИИ кнопки мыши public void MouseButtonIsDown(object sender, MouseEventArgs e) { // Запоминаем точку, в которой произошло нажатие кнопки мыши. // Когда кнопка будет отпущена, нам понадобятся ее координаты spotClicked.X = e.X;// горизонтальная координата spotClicked.Y = e.Y;// вертикальная координата } // Обработчик событий, срабатывающий при ОТЖАТИИ кнопки мыши public void MouseButtonIsUp(object sender, MouseEventArgs e) { /* Пользователь отпустил кнопку мыши! */ // Создаем прямоугольник (пока он еще не виден), ограничивающий // область изображения, с которой пользователь будет работать Rectangle r = new Rectangle(); // Левый верхний угол прямоугольника соответствует точке, // в которой была нажата кнопка мыши. // Мы сохранили ее координаты. r.X = spotClicked.X; r.Y = spotClicked.Y; // Ширина и высота прямоугольника вычисляется // путем вычитания координат мыши в точке нажатия // из текущих координат (в точке отжатия кнопки). r.Width = e.X – spotClicked.X; r.Height = e.Y – spotClicked.Y; if (e.Button == MouseButtons.Left) { /* Если была нажата и отпущена левая кнопка мыши, рисуем видимый контур прямоугольника */ // Подготовка области рисования на изображении Graphics g = this.pictureBox1.CreateGraphics(); // Рисуем красный контур прямоугольника Pen redPen = new Pen(Color.Red, 2); g.DrawRectangle(redPen, r); } else { // Если была нажата другая кнопка, вызываем // метод, подсвечивающий область изображения ChangeLightness(r); } } // Метод, увеличивающий яркость выбранного участка изображения // путем увеличения яркости каждого пикселя этого участка public void ChangeLightness(Rectangle rect) { int newRed, newGreen, newBlue; Color pixel; // Копируем изображение, загруженное в PictureBox System.Drawing.Bitmap picture = new Bitmap(this.pictureBox1.Image); // Операция увеличения яркости может занять много времени, // пользователя предупреждают, если выбран большой участок. if ((rect.Width > 150) || (rect.Height > 150)) { DialogResult result = MessageBox.Show( "Выделенная область велика! " + "Изменение яркости может требовать значительного времени!", "Warning", MessageBoxButtons.OKCancel); // При нажатии кнопки Cancel (Отмена) выходим из метода // и возвращаемся к месту его вызова if (result == DialogResult.Cancel) return; } /* Перебираем последовательно все пиксели данного участка и удваиваем значение яркости компонент RGB пикселей */ // Перебор по горизонтали слева направо... for (int x = rect.X; x < rect.X + rect.Width; x++) { // и по вертикали сверху вниз... for (int y = rect.Y; y < (rect.Y + rect.Height); y++) { // Считываем текущий пиксель pixel = picture.GetPixel(x, y); // Увеличиваем яркость цветовых компонент пикселя newRed = (int)Math.Round(pixel.R * 2.0, 0); if (newRed > 255) newRed = 255; newGreen = (int)Math.Round(pixel.G * 2.0, 0); if (newGreen > 255) newGreen = 255; newBlue = (int)Math.Round(pixel.B * 2.0, 0); if (newBlue > 255) newBlue = 255; // Присваиваем пикселю новые цветовые значения picture.SetPixel (x, y, Color.FromArgb( (byte)newRed, (byte)newGreen, (byte)newBlue)); } } // Помещаем измененную копию изображения в PictureBox, // чтобы изменения отобразились на экране this.pictureBox1.Image = picture; } static void Main() { // Создаем экземпляр класса формы Application.Run(new FunWithTheMouse()); } }Листинг 3.11.