Переместите PictureBox с помощью мыши
-
05-09-2019 - |
Вопрос
Я разрабатываю приложение для Windows mobile (Compact Framework 2.0).У него есть WinForms с PictureBox.
Я хочу переместить изображение PictureBox, но я не знаю, как это сделать, поэтому я выбираю переместить hole PictureBox.
Чтобы сделать это, я использую это событие:
private void imagenMapa_MouseMove(object sender, MouseEventArgs e)
{
imagenMapa.Left = e.X;
imagenMapa.Top = e.Y;
this.Refresh();
}
Но когда я перемещаю PictureBox, он мигает и перемещается повсюду.
Что я делаю не так?
Решение
В e.X
и e.Y
находятся относительно рамки с изображением (например,если мышь находится в левом верхнем углу окна с изображением, это равно 0,0) .
Значения для imagenMapa.Left
и imagenMapa.Top
являются относительными к форме (или любому другому элементу управления, содержащему imagenMapa
)
Если вы попытаетесь смешать значения из этих двух систем без преобразования, вы получите скачки (как вы видите).
Вероятно, вам лучше преобразовать положение мыши в ту же систему координат, которая используется объектом, содержащим поле с изображением.
Вы могли бы использовать imagenMapa.PointToScreen
чтобы получить координаты мыши в координатах экрана (или Cursor.Position
чтобы получить позицию напрямую), и yourForm.PointToClient
чтобы вернуть их обратно в виде координат.
Обратите внимание, что в зависимости от ваших потребностей вы могли бы выполнить "перемещение изображения внутри элемента управления", переопределив / обработав Paint
событие элемента управления и самостоятельно нарисуйте изображение.Если бы вы сделали это, вы могли бы сохранить все в координатах picturebox, поскольку это, скорее всего, то, что вы использовали бы при вызове graphicsObject.DrawImage
.
Другие советы
Фактический код (требуется .NET Framework 3.5 и выше, не уверен, доступно ли это в Compact Framework)...
// Global Variables
private int _xPos;
private int _yPos;
private bool _dragging;
// Register mouse events
pictureBox.MouseUp += (sender, args) =>
{
var c = sender as PictureBox;
if (null == c) return;
_dragging = false;
};
pictureBox.MouseDown += (sender, args) =>
{
if (args.Button != MouseButtons.Left) return;
_dragging = true;
_xPos = args.X;
_yPos = args.Y;
};
pictureBox.MouseMove += (sender, args) =>
{
var c = sender as PictureBox;
if (!_dragging || null == c) return;
c.Top = args.Y + c.Top - _yPos;
c.Left = args.X + c.Left - _xPos;
};
e.X и e.Y находятся в координатном пространстве PictureBox, imagenMapa.Слева и imagenMapa.Вверху находятся в координатном пространстве формы.:-)
Также не забудьте установить для вашей формы режим двойной буферизации, это может помочь с мерцанием, но для ее фактического позиционирования мне нравится предложение Дэниела Л.
Примите математику!
control.Left = control.Left - (_lastMousePos.X - currentMousePos.X);
control.Top = control.Top - (_lastMousePos.Y - currentMousePos.Y);
Краткое объяснение:Вы получаете разницу в положениях мыши и применяете ее к объекту, который хотите переместить.
Пример:Если старая позиция мыши X равна 382, а новая - 385, то разница равна -3.Если текущее положение элементов управления X равно 10, то 10 - (-3) = 13
Почему:Это работает для чего угодно и намного дешевле, чем постоянное преобразование координат туда-сюда.
На самом деле то, что вы сделали, правильно.Но вы присвоили свойство MouseMove picturebox.Вы должны присвоить это свойство Форме (background).
бывший:
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
imagenMapa.Left = e.X;
imagenMapa.Top = e.Y;
}