绘制可逆矩形

3
我从http://support.microsoft.com/kb/314945获得了一段代码来绘制可逆/橡皮筋矩形。我添加了代码,这样当我松开鼠标左键时,图像上也会创建一个矩形,然后我使用它来裁剪图像。

这个方法非常好用。唯一的问题是橡皮筋矩形不是从鼠标位置开始或结束...虽然差异很小但还是很明显。我使用相同的坐标在之后绘制矩形,确切地绘制在我的鼠标开始和结束的位置。希望能得到帮助。

以下是代码:(问题已解决-添加代码以使其他人受益)我将其制作为控件,需要时在任何地方使用!

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace CroppingControl
{
    public partial class CroppingImage : UserControl
    {
        Rectangle rc = new Rectangle();
        Boolean bHaveMouse;
        Point ptOriginal = new Point();
        Point ptLast = new Point();
        Image Pic;

        public CroppingImage()
        {
            InitializeComponent();
            pictureBox1.MouseDown += new MouseEventHandler(MyMouseDown);
            pictureBox1.MouseUp += new MouseEventHandler(MyMouseUp);
            pictureBox1.MouseMove += new MouseEventHandler(MyMouseMove);
            bHaveMouse = false;
        }


        public Image Image
        {
            set
            {
                pictureBox1.Image = value;
                Pic = value;
            }
            get
            {
                return pictureBox1.Image;
            }
        }

        public void MyMouseDown(Object sender, MouseEventArgs e)
        {
            pictureBox1.Image = Pic;
            // Make a note that we "have the mouse".

            bHaveMouse = true;
            // Store the "starting point" for this rubber-band rectangle.
            ptOriginal.X = e.X;
            ptOriginal.Y = e.Y;
            // Special value lets us know that no previous
            // rectangle needs to be erased.
            ptLast.X = -1;
            ptLast.Y = -1;
        }

        // Convert and normalize the points and draw the reversible frame.
        private void MyDrawReversibleRectangle(Point p1, Point p2)
        {
            Point px = p1;
            Point py = p2;

            // Convert the points to screen coordinates.
            p1 = PointToScreen(p1);
            p2 = PointToScreen(p2);
            // Normalize the rectangle.
            if (p1.X < p2.X)
            {
                rc.X = p1.X;
                rc.Width = p2.X - p1.X;
            }
            else
            {
                rc.X = p2.X;
                rc.Width = p1.X - p2.X;
            }
            if (p1.Y < p2.Y)
            {
                rc.Y = p1.Y;
                rc.Height = p2.Y - p1.Y;
            }
            else
            {
                rc.Y = p2.Y;
                rc.Height = p1.Y - p2.Y;
            }
            // Draw the reversible frame.
            ControlPaint.DrawReversibleFrame(rc, Color.Black, FrameStyle.Dashed);

            rc.X = px.X;
            rc.Y = px.Y;

        }
        // Called when the left mouse button is released.
        public void MyMouseUp(Object sender, MouseEventArgs e)
        {
            // Set internal flag to know we no longer "have the mouse".
            bHaveMouse = false;
            // If we have drawn previously, draw again in that spot
            // to remove the lines.
            if (ptLast.X != -1)
            {
                Point ptCurrent = new Point(e.X, e.Y);
                MyDrawReversibleRectangle(ptOriginal, ptLast);
                Graphics graphics = pictureBox1.CreateGraphics();
                Pen pen = new Pen(Color.Gray, 2);
                pen.DashStyle = System.Drawing.Drawing2D.DashStyle.DashDot;
                graphics.DrawRectangle(pen, rc);

            }
            // Set flags to know that there is no "previous" line to reverse.
            ptLast.X = -1;
            ptLast.Y = -1;
            ptOriginal.X = -1;
            ptOriginal.Y = -1;
        }
        // Called when the mouse is moved.
        public void MyMouseMove(Object sender, MouseEventArgs e)
        {
            Point ptCurrent = new Point(e.X, e.Y);
            // If we "have the mouse", then we draw our lines.
            if (bHaveMouse)
            {
                // If we have drawn previously, draw again in
                // that spot to remove the lines.
                if (ptLast.X != -1)
                {
                    MyDrawReversibleRectangle(ptOriginal, ptLast);
                }
                // Update last point.
                ptLast = ptCurrent;
                // Draw new lines.
                MyDrawReversibleRectangle(ptOriginal, ptCurrent);
            }
        }

    }
}

你能添加一些代码吗?你是如何获取鼠标坐标的,又是如何使用这些坐标的? - Hans Kesting
示例代码是否在没有小差异的情况下正常工作?如果是,请发布您的代码,以便可以看到差异发生的位置。 - Gambrinus
1个回答

2

ControlPaint.DrawReversibleFrame 使用屏幕坐标在屏幕上绘制一个矩形(即不考虑应用程序窗口),这对于处理拖动鼠标操作非常有用,因为鼠标可能移动到应用程序窗口之外。如果您要直接使用这些坐标在应用程序中进行绘画,则它们会失效,因为您正在绘制的控件的坐标是相对于该控件的原点(通常是左上角)的。

要使用屏幕坐标,您首先需要使用 PointToClient()RectangleToClient() 方法将其转换为相应控件的控件坐标,例如:

// panel`s OnPaint
Rectangle screenRectangle = ...
Rectangle clientRectangle = panel.RectangleToClient(screenRectangle);
graphics.DrawRectangle(Pens.Red, clientRectangle);

这是我使用的代码public partial class Form2 : Form      {          矩形rc = new Rectangle();          布尔型bHaveMouse;          点ptOriginal = new Point();          点ptLast = new Point();          PictureBoxpic = null;         Form1表单;         public Form2(Form1 form1,PictureBox picturebox)          {              InitializeComponent();              pic = picturebox;              PictureBox1.Image = picturebox.Image;              形式=表格1;          } - Umar
我是这个网站的新手...代码很长,我无法将所有代码粘贴到评论框中...但我没怎么改动代码,问题也在它的位置上离我点击的地方大约20像素的距离处... - Umar
首先,我想感谢大家的帮助 :-) 我刚刚检查了代码...微软链接提供的代码没有问题...问题在于我的代码...区别在于提供的代码在表单上绘制矩形,而我将其更改为在图片框上绘制。我能把我的所有代码都粘贴在这里吗?? - Umar
不是在评论中,而是您可以编辑您的问题。(要格式化代码,只需在每行开头放置四个空格。) - Paul Ruane
@Umar:顺便说一下,如果你所说的是真的(关于表单与图片框),那么你应该可以简单地更改从屏幕坐标转换为客户端坐标的代码,使用PictureBox而不是Form,即在你的PictureBox上调用RectangleToClient。 - Paul Ruane
问题得到了显著的解决,当我将代码添加为控件时。仍然不知道是什么原因导致了这个问题。请检查代码,我相信它会对大家有所帮助! - Umar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接