【问题标题】:How to select an area on a PictureBox.Image with mouse in C#如何在 C# 中使用鼠标选择 PictureBox.Image 上的区域
【发布时间】:2019-04-13 18:53:03
【问题描述】:

我只是想在我的 picturebox.image 上进行选择,但这比一些烦人的情况更糟。我想到了主图片框上方的另一个图片框,但它对我来说似乎很懒惰。我需要知道是否有一种方法可以在图片框上创建一个选择区域(这将是半透明的蓝色区域)。我要用鼠标绘制它,它不应该改变我正在处理的图像。

样本:

    // Start Rectangle
    //
    private void pictureBox1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
    {
        // Determine the initial rectangle coordinates...
        RectStartPoint = e.Location;
        Invalidate();
    }

    // Draw Rectangle
    //
    private void pictureBox1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
    {
        if (e.Button != MouseButtons.Left)
            return;
        Point tempEndPoint = e.Location;
        Rect =
            new Rectangle(
                Math.Min(RectStartPoint.X, tempEndPoint.X),
                Math.Min(RectStartPoint.Y, tempEndPoint.Y),
                Math.Abs(RectStartPoint.X - tempEndPoint.X),
                Math.Abs(RectStartPoint.Y - tempEndPoint.Y));
        Invalidate(Rect);
    }

    // Draw Area
    //
    private void pictureBox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
    {
        // Draw the rectangle...
        if (pictureBox1.Image != null)
        {
            Brush brush = new SolidBrush(Color.FromArgb(128, 72, 145, 220));
            e.Graphics.FillRectangle(brush, Rect);
        }
    }

【问题讨论】:

  • 那么你想在pictureBox中的图像上创建一个选择框吗?选择框会不会和在桌面上点击拖拽一样,创建一个透明的蓝色方块?

标签: c# .net winforms system.drawing


【解决方案1】:

我使用了你的代码,你就快到了。您需要使 pictureBox1 而不是矩形无效。我还添加了对 Rect 的检查,因此它在未初始化或没有大小时不会被绘制。

另一个重要的变化:我只创建了一次矩形,并调整了它的位置和大小。少清理垃圾!

编辑

我为矩形添加了鼠标右键单击处理程序。

private Point RectStartPoint;
private Rectangle Rect = new Rectangle();
private Brush selectionBrush = new SolidBrush(Color.FromArgb(128, 72, 145, 220));

// Start Rectangle
//
private void pictureBox1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
    // Determine the initial rectangle coordinates...
    RectStartPoint = e.Location;
    Invalidate();
}

// Draw Rectangle
//
private void pictureBox1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
    if (e.Button != MouseButtons.Left)
        return;
    Point tempEndPoint = e.Location;
    Rect.Location = new Point(
        Math.Min(RectStartPoint.X, tempEndPoint.X),
        Math.Min(RectStartPoint.Y, tempEndPoint.Y));
    Rect.Size = new Size(
        Math.Abs(RectStartPoint.X - tempEndPoint.X),
        Math.Abs(RectStartPoint.Y - tempEndPoint.Y));
    pictureBox1.Invalidate();
}

// Draw Area
//
private void pictureBox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
    // Draw the rectangle...
    if (pictureBox1.Image != null)
    {
        if (Rect != null && Rect.Width > 0 && Rect.Height > 0)
        {
            e.Graphics.FillRectangle(selectionBrush, Rect);
        }
    }
}

private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Right)
    {
        if (Rect.Contains(e.Location))
        {
            Debug.WriteLine("Right click");
        }
    }
}

【讨论】:

  • 你能告诉我如何在该选择上创建右键单击事件吗?
  • 顺便说一句:在您的实现中,画笔被一次又一次地创建。尽量防止这种情况。我也会为此调整我的代码。
  • 为什么一次次创建画笔会出现问题?这是一项昂贵的手术吗?
  • @kdbanman - 是的。除了它是多余的之外,Brushes 还声称不受管理的资源。当您不释放这些画笔(和其他 GDI 对象)时,仍将分配此内存。根据鼠标移动的频率,代码可能会泄漏相当多的内存。另请参阅此答案:stackoverflow.com/a/1336752/563088
  • @kdbanman - Invalidate() 导致重绘 PictureBox。重绘调用引发 Paint 事件,并且 Paint 事件处理程序绘制矩形。这个解决方案的好处是,无论何时重绘 PictureBox(移动、调整大小、缩放……),矩形都会跟随并始终不同步。此外,Paint 事件处理程序接收对绘制矩形所需的图形对象的引用,因此我们不必自己创建(和处置)图形对象。
【解决方案2】:
   private int xUp, yUp, xDown,yDown;
        private Rectangle rectCropArea;
   private void SrcPicBox_MouseUp(object sender, MouseEventArgs e)
        {
            //pictureBox1.Image.Clone();
            xUp = e.X;
            yUp = e.Y;
            Rectangle rec = new Rectangle(xDown,yDown,Math.Abs(xUp xDown),Math.Abs(yUp-yDown));
            using (Pen pen = new Pen(Color.YellowGreen, 3))
            {

                SrcPicBox.CreateGraphics().DrawRectangle(pen, rec);
            }
            rectCropArea = rec;
        }
 private void SrcPicBox_MouseDown(object sender, MouseEventArgs e)
        {
            SrcPicBox.Invalidate();

            xDown = e.X;
            yDown = e.Y;
        }
 private void btn_upload_Click(object sender, EventArgs e)
        {
            OpenFileDialog opf = new OpenFileDialog();
          //  PictureBox SrcPicBox = new PictureBox();
            opf.Filter = "ALL images(*.*)|*.*";
            if (opf.ShowDialog() == DialogResult.OK)
            {
                string name = opf.SafeFileName;
                string filepath = opf.FileName;
                File.Copy(filepath, name, true);
                SrcPicBox.Image = Image.FromFile(opf.FileName);
            }
 private void btn_crop_Click(object sender, EventArgs e)
        {
            pictureBox3.Refresh();
            //Prepare a new Bitmap on which the cropped image will be drawn
            Bitmap sourceBitmap = new Bitmap(SrcPicBox.Image, SrcPicBox.Width, SrcPicBox.Height);
            Graphics g = pictureBox3.CreateGraphics();

            //Draw the image on the Graphics object with the new dimesions
            g.DrawImage(sourceBitmap, new Rectangle(0, 0, pictureBox3.Width, pictureBox3.Height), rectCropArea, GraphicsUnit.Pixel);
            sourceBitmap.Dispose();
        }

【讨论】:

  • 请添加一些描述您的代码的作用以及它如何提供问题的答案。
  • 感谢您花时间提供解决方案,但是,一个好的答案还应该说明它为什么会解决 OP 的问题,如果可能,请指出确切的OP需要解决的事情。滚动大段代码通常会让人们失望。尝试编辑以使其对 OP 和社区更有用。
  • 我不得不改变=>这一行: Bitmap sourceBitmap = new Bitmap(SrcPicBox.Image, SrcPicBox.Width, SrcPicBox.Height); to: 位图 sourceBitmap = new Bitmap(SrcPicBox.Image, SrcPicBox.Image.Width, SrcPicBox.Image.Height);为了得到正确的结果。
猜你喜欢
  • 2012-06-15
  • 2014-09-04
  • 1970-01-01
  • 2011-08-21
  • 2011-10-18
  • 1970-01-01
  • 2017-06-30
  • 2021-12-03
  • 1970-01-01
相关资源
最近更新 更多