БлогNot. Visual C++/CLI: рисуем линию на PictureBox "как в Paint"

Помощь дата->рейтинг Поиск Почта RSS канал Статистика nickolay.info Домой

Visual C++/CLI: рисуем линию на PictureBox "как в Paint"

То есть, при движении мыши с зажатой кнопкой линия должна динамически обновляться, а при отпускании кнопки добавляться на существующий рисунок. Так как PictureBox удобно сохранять и легко снабдить полосами прокрутки, будем рисовать на ней. Компонента может быть частью интерфейса приложения как в этой заметке или растянутой на всю форму. Проект создан как приложение Windows Forms, код проверен в Visual Studio 2015.

Опишем в классе формы (после директивы #pragma endregion) необходимые данные:

private:
 Point p1, p2; //начало и конец линии
 Pen^ pen1; //перо
 Bitmap ^Img1; //основная картинка, на которой рисуем
 bool isPressed; //флажок "кнопка мыши зажата"

Для самой формы нам понадобится запрограммировать только событие Load, где мы инициализируем всё, что нужно - создадим рисунок по текущим размерам PictureBox, назначим его компоненте, создадим перо и выставим в "ложь" флажок:

private: System::Void MyForm_Load(System::Object^  sender, System::EventArgs^  e) {
 Img1 = gcnew Bitmap(pictureBox1->Width, pictureBox1->Height);
 pictureBox1->Image = Img1;
 pen1 = gcnew Pen(Color::Black);
 isPressed = false;
}

Всё остальное запрограммируем в событиях PictureBox. На нажатие кнопки мыши будем включать флажок и запоминать место клика p1:

private: System::Void pictureBox1_MouseDown(System::Object^  sender, 
 System::Windows::Forms::MouseEventArgs^  e) {
 isPressed = true;
 p1 = e->Location;
}

На отпускание кнопки получим координаты второй точки p2 и соединим её с первой, проведя линию на образе Img1. В реальном коде можно добавлять точки в какой-то контейнер, например, в список как здесь.

private: System::Void pictureBox1_MouseUp(System::Object^  sender, System::Windows::Forms::MouseEventArgs^  e) {
 p2 = e->Location;
 Graphics ^gr = Graphics::FromImage(Img1);
 gr->DrawLine(pen1,p1,p2);
 gr->Save();
 isPressed = false;
 delete gr;
 pictureBox1->Invalidate();
}

На перемещение мыши обработка будет немного хитрей. Если кнопка не зажата, ничего делать не нужно, а в противном случае будем проводить текущую линию на копии рисунка Img2, созданной из Img1, чтобы не получилось "веера" из линий при перемещении мыши с зажатой кнопкой. Img2 всё равно придётся временно назначить рисунком для PictureBox, чтобы линия была видна в процессе движения мыши.

private: System::Void pictureBox1_MouseMove(System::Object^  sender, System::Windows::Forms::MouseEventArgs^  e) {
 if (!isPressed) return; //Кнопка не зажата - выйти
 Point p2 = e->Location;
 Bitmap ^Img2 = gcnew Bitmap(Img1);
 pictureBox1->Image = Img2;
 Graphics ^gr = Graphics::FromImage(Img2);
 gr->DrawLine(pen1, p1, p2);
 delete gr;
 pictureBox1->Invalidate();
}

Это всё, приложение можно собирать.

P.S. Здесь у нас все координаты были "внутри PictureBox" и получались непосредственно из аргумента MouseEventArgs обработчика события. По-другому можно делать так:

форма->Location.X, форма->Location.Y
//Координаты верхнего левого угла формы

Cursor->Position.X, Cursor->Position.Y
//координаты курсора относительно экрана

int x1 = Cursor->Position.X - this->Location.X;
int y1 = Cursor->Position.Y - this->Location.Y;
//координаты мыши относительно левого верхнего угла формы - разность

теги: studio c++ программирование графика учебное

комментарии (0)

14.11.2017, 13:29; рейтинг: 41

  свежие записипоиск по блогуоткомментироватьстатистика

Наверх Яндекс.Метрика
© PerS
вход