Как нарисовать прямоугольник в любом направлении после MouseDown, используя C#? - PullRequest
1 голос
/ 02 февраля 2020

Как я могу нарисовать прямоугольник во всех направлениях? Текущий код:

private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
    // Starting point of the selection:
    if (e.Button == MouseButtons.Left)
    {
        _selecting = true;
        _selection = new Rectangle(new Point(e.X, e.Y), new Size());
    }
}

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
    // Update the actual size of the selection:
    if (_selecting)
    {
        _selection.Width = e.X - _selection.X;
        _selection.Height = e.Y - _selection.Y;
        pictureBox1.Refresh(); // redraw picturebox

    }
}

private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left && _selecting)
    {
        _selecting = false;
    }
}

Это позволяет мне набрать MouseDown, а затем рисовать вниз и вправо, но я не могу рисовать ни в каком другом направлении, кроме точки привязки. Как нарисовать прямоугольник в любом направлении, например, Microsoft Paint?

enter image description here

Сначала я попробовал:

_selection.Width = Math.Abs(e.X - _selection.X);
_selection.Height = Math.Abs(e.Y - _selection.Y);

Но это создает забавный зеркальный эффект (чего я не хочу). Затем я попытался простой сдвиг:

_selection.X = _selection.Left - 5;

Это сделало то, что я ожидал, и переехал Стать c прямоугольник 5 единиц влево, так что я думал, что это было бы простым дело постоянно смещая точку привязки во время Событие рисования:

private void UpdateRectange(Point newPos)
{
    var width = newPos.X - _selection.X;
    var height = newPos.Y - _selection.Y;
    _selection.Width = Math.Abs(width);
    _selection.Height = Math.Abs(height);
    if (width < 0 && height > 0) // move down (+) and left (-)
    {
        //_selection.X = _selection.Left + width;
        _selection.Offset(width, 0);
    }
    uxScreenGrab.Refresh(); // redraw picturebox
}

Но это привело к перемещению вертикальной линии через экран влево при перемещении влево от исходной точки привязки. Ширина по некоторым причинам не обновляется должным образом.

enter image description here

Ответы [ 3 ]

2 голосов
/ 02 февраля 2020

Вот еще один фрагмент для рисования прямоугольника выбора на PictureBox:

//...
private Point startPoint;
private Point endPoint;
private readonly Pen P1 = new Pen(Color.SteelBlue, 2) {
    Alignment = PenAlignment.Center, DashStyle = DashStyle.Dash};
//...

Установите startPoint в событии MouseDown и сбросьте переменные endPoint:

private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        startPoint = new Point(e.X, e.Y);
        endPoint = Point.Empty;
    }
}

Установите метод endPoint и вызовите Invalidate() в событии MouseMove:

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
    var p = new Point(e.X, e.Y);

    if (e.Button == MouseButtons.Left &&
        !p.Equals(startPoint))
    {
        endPoint = p;
        pictureBox1.Invalidate();
    }
}

Также вызовите Invalidate() в событии MouseUp, чтобы удалить прямоугольник выбора:

private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
    pictureBox1.Invalidate();
}

Нарисуйте прямоугольник выбора:

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    if(MouseButtons == MouseButtons.Left &&
        !startPoint.Equals(endPoint) &&
        !endPoint.Equals(Point.Empty))
    {
        var g = e.Graphics;
        var rect = Rectangle.Empty;

        if(startPoint.X < endPoint.X)
        {
            rect.X = startPoint.X;
            rect.Width = endPoint.X - startPoint.X;
        }
        else
        {
            rect.X = endPoint.X;
            rect.Width = startPoint.X - endPoint.X;
        }
        if(startPoint.Y < endPoint.Y)
        {
            rect.Y = startPoint.Y;
            rect.Height = endPoint.Y - startPoint.Y;
        }
        else
        {
            rect.Y = endPoint.Y;
            rect.Height = startPoint.Y - endPoint.Y;
        }
        g.DrawRectangle(P1, rect);
    }
}

И не забудьте очистить:

private void YourForm_FormClosing(object sender, FormClosingEventArgs e)
{
    P1.Dispose();
}

Сохраняйте это простым.

SOQ60022534

Похожие сообщения

Как вызвать метод, который использует PaintEventArgs и координаты переменных

2 голосов
/ 02 февраля 2020

Решение, предложенное в вопросе, выглядит хорошо:

_selection.Width = Math.Abs(e.X - initiallySelectedX);
_selection.Height = Math.Abs(e.Y - initiallySelectedY);

... но Вы должны переместить начало прямоугольника, когда (eX - initialSelectedX) <0 </p>

Так что, вероятно, Вы хотите добавить что-то подобное в Ваш код:

var diffX = e.x - initiallySelectedX;
if (diffX < 0) _selection.X = initiallySelectedX - diffX;
var diffY = e.y - initiallySelectedY;
if (diffY < 0) _selection.Y = initiallySelectedY - diffY;

Где initiallySelectedX и initiallySelectedY - переменные, установленные onMouseDown. это только грубая идея. Идея заключается в том, что ширина и высота прямоугольника не могут быть отрицательными !!

1 голос
/ 02 февраля 2020

ОБНОВЛЕНИЕ:

Отслеживание начальной точки события MouseDown позволяет корректно обновить точку привязки:

private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
    // Starting point of the selection:
    if (e.Button == MouseButtons.Left)
    {
        _selecting = true;
        _selection = new Rectangle(new Point(e.X, e.Y), new Size());
        _startingPoint = e.Location;
    }
}

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
    // Update the actual size of the selection:
    if (_selecting)
    {
        UpdateRectange(e.Location);
    }
}

private void UpdateRectange(Point newPos)
{
    var diffX = newPos.X - _startingPoint.X;
    var diffY = newPos.Y - _startingPoint.Y;
    var newSize = new Size(Math.Abs(diffX), Math.Abs(diffY));
    if (diffX > 0 && diffY > 0)
    {
        _selection = new Rectangle(_startingPoint, newSize);
    }
    else if (diffX < 0 && diffY < 0)
    {
        _selection = new Rectangle(newPos, newSize);
    }
    else if (diffX > 0 && diffY < 0)
    {
        _selection = new Rectangle(new Point(_startingPoint.X, _startingPoint.Y + diffY), newSize);
    }
    else
    {
        _selection = new Rectangle(new Point(_startingPoint.X + diffX, _startingPoint.Y), newSize);
    }
    uxScreenGrab.Invalidate();
}

ОБНОВЛЕНИЕ 2:

Re -пишите UpdateRectangle, чтобы просто переместить точку привязки, вместо того, чтобы создавать экземпляры при каждом вызове:

private void UpdateRectange(Point newPos)
{
    var diffX = newPos.X - _startingPoint.X;
    var diffY = newPos.Y - _startingPoint.Y;
    var newSize = new Size(Math.Abs(diffX), Math.Abs(diffY));
    if (diffX > 0 && diffY > 0)
    {
        _selection.Size = newSize;
    }
    else if (diffX < 0 && diffY < 0)
    {
        _selection.Location = newPos;
        _selection.Size = newSize;
    }
    else if (diffX > 0 && diffY < 0)
    {
        _selection.Y = _startingPoint.Y + diffY;
        _selection.Size = newSize;
    }
    else
    {
        _selection.X = _startingPoint.X + diffX;
        _selection.Size = newSize;
    }
    uxScreenGrab.Invalidate();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...