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

#c# #winforms #grid #picturebox

#c# #winforms #сетка #picturebox

Вопрос:

У меня есть приведенный ниже, который рисует прямоугольник при перетаскивании мышью, а также скрипт рисования сетки, который рисует сетку размером 32×32 на поле с изображением. что я пытаюсь сделать, это привязать прямоугольник к сетке, а затем сделать снимок экрана внутри прямоугольника.

У меня есть бит снимка экрана, и рисование прямоугольника просто не работает бит привязки к сетке.

 private bool _selecting;
private Rectangle _selection;

private void picCanvas_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        _selecting = true;
        _selection = new Rectangle(new Point(e.X, e.Y), new Size());
    }
}

private void picCanvas_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
    if (_selecting)
    {
        _selection.Width = e.X - _selection.X;
        _selection.Height = e.Y - _selection.Y;

        pictureBox1.Refresh();
    }
}

public Image Crop(Image image, Rectangle selection)
{
    Bitmap bmp = image as Bitmap;

    // Check if it is a bitmap:
    if (bmp == null)
        throw new ArgumentException("No valid bitmap");

    // Crop the image:
    Bitmap cropBmp = bmp.Clone(selection, bmp.PixelFormat);

    // Release the resources:
    image.Dispose();

    return cropBmp;
}

private void picCanvas_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left amp;amp;
        _selecting amp;amp;
        _selection.Size != new Size())
    {
        // Create cropped image:
        //Image img = Crop(pictureBox1.Image, _selection);

        // Fit image to the picturebox:
        //pictureBox1.Image = img;

        _selecting = false;
    }
    else
        _selecting = false;
}

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    if (_selecting)
    {
        // Draw a rectangle displaying the current selection
        Pen pen = Pens.GreenYellow;
        e.Graphics.DrawRectangle(pen, _selection);
    }

    Graphics g = e.Graphics;
    int numOfCells = amount;
    Pen p = new Pen(Color.LightGray);

    for (int y = 0; y < numOfCells;   y)
    {
        g.DrawLine(p, 0, y * ysize, numOfCells * ysize, y * ysize);
    }

    for (int x = 0; x < numOfCells;   x)
    {
        g.DrawLine(p, x * xsize, 0, x * xsize, numOfCells * xsize);
    }
}
 

Комментарии:

1. Я не вижу привязки к сеточному коду. Как это может работать?

2. Вы спрашиваете, как будет работать абстрактная идея «привязки» окна? Я бы объявил snapPadDist , и если значение мыши при перетаскивании находится в пределах snapPadDist целевого прямоугольника, то просто нарисуйте прямоугольник того же размера, что и целевой прямоугольник.

Ответ №1:

Сначала я бы объявил метод привязки

 private Point SnapToGrid(Point p)
{
    double x = Math.Round((double)p.X / xsize) * xsize;
    double y = Math.Round((double)p.Y / ysize) * ysize;
    return new Point((int)x, (int)y);
}
 

Затем вы можете инициализировать выделение следующим образом при наведении курсора мыши:

 _selection = new Rectangle(SnapToGrid(e.Location), new Size());
 

И вы можете настроить ширину в MouseMove следующим образом:

 Point dest = SnapToGrid(e.Location);
_selection.Width = dest.X - _selection.X;
_selection.Height = dest.Y - _selection.Y;