using System;
using System.Collections;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;
using PhotoSprite.ImageProcessing;namespace PhotoSprite.Tool
{
  /// <summary>
  /// 矩形工具类
  /// </summary>
  public class RectangleTool : Tool
  {
    private Canvas canvas = null;
    private Bitmap image = null;
    private Bitmap srcImage = null;
    private Graphics gImage;
    private Graphics gSurface;
    private bool mouseDown = false;
    private Point startPoint, lastPoint;
    private Pen pen = null;    /// <summary>
    /// 使用矩形工具
    /// </summary>
    /// <param name="parent">画布</param>
    public RectangleTool(Canvas parent)
    {
      this.canvas = parent;
      gSurface = canvas.CreateGraphics();
    }    public void OnActivate()
    {
      this.canvas.MouseDown += this.OnMouseDown;
      this.canvas.MouseMove += this.OnMouseMove;
      this.canvas.MouseUp += this.OnMouseUp;
    }    public void OnDeactivate()
    {
      this.canvas.MouseDown -= this.OnMouseDown;
      this.canvas.MouseMove -= this.OnMouseMove;
      this.canvas.MouseUp -= this.OnMouseUp;
    }    public void OnMouseDown(object sender, MouseEventArgs e)
    {
      if (((e.Button & MouseButtons.Left) == MouseButtons.Left) ||
        ((e.Button & MouseButtons.Right) == MouseButtons.Right))
      {
        mouseDown = true;
        lastPoint = startPoint = new Point(e.X, e.Y);        // 左键为前景颜色,右键为背景颜色
        if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
        {
          pen = new Pen(new SolidBrush(this.ForeColor), this.BrushWidth);
        }
        else if ((e.Button & MouseButtons.Right) == MouseButtons.Right)
        {
          pen = new Pen(new SolidBrush(this.BackColor), this.BrushWidth);
        }        // 锁定画布图像
        this.image = this.canvas.Image;
        this.srcImage = (Bitmap)this.image.Clone();
        gImage = System.Drawing.Graphics.FromImage(image);
      }
    }    public void OnMouseMove(object sender, MouseEventArgs e)
    {
      if (mouseDown)
      {
        Point mouseXY = new Point(e.X, e.Y);
        mouseXY = Function.PointInRectangle(mouseXY, this.canvas.Bounds);
        if (mouseXY.X == this.canvas.Width - 1) mouseXY.X = this.canvas.Width - 2;
        if (mouseXY.Y == this.canvas.Height - 1) mouseXY.Y = this.canvas.Height - 2;
        
        // 消除上次痕迹
        Rectangle lastRect = Function.PointsToRectangle(startPoint, lastPoint);        
        Rectangle lastOutlineRect = lastRect;
        lastOutlineRect.Inflate(2, 2);
        Rectangle lastInteriorRect = lastRect;
        lastInteriorRect.Inflate(-2, -2);
        Region invalidRegion = new Region(lastOutlineRect);
        invalidRegion.Xor(lastInteriorRect);        this.canvas.Invalidate(invalidRegion);
        this.gImage.DrawImage((Bitmap)this.srcImage.Clone(), lastOutlineRect, lastOutlineRect, GraphicsUnit.Pixel);
        
        // 绘制表面
        Rectangle rect = Function.PointsToRectangle(startPoint, mouseXY);
        //this.gSurface.DrawRectangle(pen, rect);        // 绘制到图像
        this.gImage.DrawRectangle(pen, rect);        lastPoint = mouseXY;
      }
    }    public void OnMouseUp(object sender, MouseEventArgs e)
    {
      if (mouseDown)
      {
        Point mouseXY = new Point(e.X, e.Y);        // 绘制矩形
        Graphics g = Graphics.FromImage(this.srcImage);
        g.DrawRectangle(pen, Function.PointsToRectangle(startPoint, mouseXY));
        this.gImage.DrawImage((Bitmap)this.srcImage.Clone(), 0,0);        startPoint = Point.Empty;
        lastPoint = Point.Empty;
        mouseDown = false;        pen.Dispose();
        this.canvas.Invalidate();        // 触发绘图结束事件
        OnDrawingFinished();
      }
    }
    /// <summary>
    /// 在绘图结束时发生
    /// </summary>
    public event EventHandler DrawingFinished;
    protected void OnDrawingFinished()
    {
      if (DrawingFinished != null)
      {
        DrawingFinished(this, EventArgs.Empty);
      }
    }
  }
}

解决方案 »

  1.   

    if (mouseDown)//判断是按下状态
    大致就是随着鼠标位置改变而画,有很多自定义的东西,自己慢慢分析吧
      

  2.   

    这里就一个Canvas 是自定义的。using System;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Windows.Forms;
    using PhotoSprite.ImageProcessing;namespace PhotoSprite
    {
      public partial class Canvas : UserControl
      {
        private Bitmap image = null;
        private string imageFile = "";
        private double zoom = 1.0;    private GraphicsPath selectedPath = new GraphicsPath();
        private int dancingAnts = 0;
        private static Pen outlinePen = null;
        private static Pen antPen = null;
        /// <summary>
        /// 获取或设置图像
        /// </summary>
        public Bitmap Image
        {
          get
          {
            return image;
          }
          set
          {
            image = value;
            this.Invalidate();
          }
        }    /// <summary>
        /// 获取或设置图像文件
        /// </summary>
        public string ImageFile
        {
          get
          {
            return imageFile;
          }
          set
          {
            imageFile = value;        if (imageFile != "")
            {
              Graphic myGraphic = new Graphic();
              this.Image = myGraphic.Open(imageFile);
            }
          }
        }    /// <summary>
        /// 获取或设置画布缩放系数
        /// </summary>
        public double Zoom
        {
          get
          {
            return zoom;
          }
          set
          {
            zoom = value;
            this.Invalidate();
          }
        }    /// <summary>
        /// 获取或设置选区
        /// </summary>
        public GraphicsPath SelectedPath
        {
          get
          {
            return selectedPath;
          }
          set
          {
            if (selectedPath != null)
              selectedPath.Reset();
            selectedPath = value;
          }
        }    /// <summary>
        /// 获取 bool 值,以指示是否选区为空
        /// </summary>
        public bool IsSelectionEmpty
        {
          get
          {
            return selectedPath.PointCount == 0;
          }
        }    /// <summary>
        /// 获取选区
        /// </summary>
        public Region SelectedRegion
        {
          get
          {
            if (IsSelectionEmpty)
              return new Region(new Rectangle(0, 0, this.Size.Width, this.Size.Height));
            else
              return new Region(selectedPath);
          }
        }    /// <summary>
        /// 画布
        /// </summary>
        public Canvas()
        {
          InitializeComponent();      this.ResizeRedraw = true;
          this.SetStyle( ControlStyles.UserPaint |
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.OptimizedDoubleBuffer, true);      this.SetStyle(ControlStyles.UserMouse, true);  //控制鼠标完成事件
        }    protected override void OnLoad(EventArgs e)
        {
          base.OnLoad(e);      // 绘制背景,将黑白方块交叉出现的花纹样式视作透明背景
          Color black = Color.FromArgb(0xFF, 0xDF, 0xDF, 0xDF);
          Color white = Color.White;      Bitmap buffer = new Bitmap(16, 16);
          Graphics g = System.Drawing.Graphics.FromImage(buffer);
          g.FillRectangle(new SolidBrush(black), 0, 0, 8, 8);
          g.FillRectangle(new SolidBrush(white), 8, 0, 8, 8);
          g.FillRectangle(new SolidBrush(white), 0, 8, 8, 8);
          g.FillRectangle(new SolidBrush(black), 8, 8, 8, 8);      this.BackgroundImage = buffer;
        }    protected override void OnResize(EventArgs e)
        {
          base.OnResize(e);
        }    protected override void OnPaint(PaintEventArgs e)
        {
          //base.OnPaint(e);      // 绘制图像
          if (image != null)
          {
            this.Size = new Size((int)(this.image.Width * zoom), (int)(this.image.Height * zoom));        e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
            e.Graphics.DrawImage(image,
              new Rectangle(0, 0, this.Width, this.Height),
              new Rectangle(0, 0, image.Width, image.Height),
              GraphicsUnit.Pixel
              );
          }
          if (!IsSelectionEmpty)
          {
            DrawSelectionOutline(e.Graphics, selectedPath);
          }
        }    protected override void OnMouseDown(MouseEventArgs e)
        {
          base.OnMouseDown(e);
        }    protected override void OnMouseMove(MouseEventArgs e)
        {
          base.OnMouseMove(e);
        }    protected override void OnMouseUp(MouseEventArgs e)
        {
          base.OnMouseUp(e);
        }    private void DrawSelectionOutline(Graphics g, GraphicsPath outline)
        {
          if (outline == null)
          {
            return;
          }      g.SmoothingMode = SmoothingMode.AntiAlias;      // 绘制轮廓线
          if (outlinePen == null)
          {
            outlinePen = new Pen(Color.FromArgb(200, Color.Black), 1.0f);
            outlinePen.Alignment = PenAlignment.Outset;
            outlinePen.LineJoin = LineJoin.Round;
          }      // 绘制蚂蚁线
          if (antPen == null)
          {
            antPen = new Pen(Color.White, 1.0f);
            antPen.Alignment = PenAlignment.Outset;
            antPen.LineJoin = LineJoin.Round;
            antPen.MiterLimit = 2;
            antPen.Width = 1.0f;
            antPen.DashStyle = DashStyle.Dash;
            antPen.DashPattern = new float[] { 4, 4 };
            antPen.DashOffset = 4.0f;
          }
          g.PixelOffsetMode = PixelOffsetMode.Default;
          g.DrawPath(outlinePen, outline);
          antPen.DashOffset = dancingAnts;
          g.DrawPath(antPen, outline);      // 填充一个蓝色区域
          g.FillPath(new SolidBrush(Color.FromArgb(60, Color.Cyan)), outline);
        }    private void selectionTimer_Tick(object sender, EventArgs e)
        {
          if (!IsSelectionEmpty)
          {
            dancingAnts = unchecked(dancingAnts + 1);
            this.Invalidate();
          }
        }  }
    }
      

  3.   


    是啊,《图像编程精髓》的一段代码。CSDN上有源代码下载!!
      

  4.   

    RectangleTool 绘制矩形的类
    public void OnMouseMove(object sender, MouseEventArgs e)
        {
            //判断OnMouseDown是否正确执行,即鼠标是否按键正确
            //鼠标移到的过程中必须鼠标左键或右键按住移到,如果移到的过程鼠标释放了
            //将触发OnMouseUp事件,mouseDown将赋值为false
            //接下去不管鼠标怎么移到,都不会在执行这个if里面的代码
            //这个过程表示一个绘制矩形的过程:鼠标单击画布某点 - 鼠标按住不放拖动 - 鼠标释放 - 矩形绘制成功
            if (mouseDown)
            {
                //获取鼠标移到到的某个点的位置
                Point mouseXY = new Point(e.X, e.Y);            //将鼠标移到的点和画布边缘进行比较,如果移动到画布外面,就修改mouseXY的x和y
                //这个主要是防止矩形绘制到画布外面
                mouseXY = Function.PointInRectangle(mouseXY, this.canvas.Bounds);
                if (mouseXY.X == this.canvas.Width - 1) mouseXY.X = this.canvas.Width - 2;
                if (mouseXY.Y == this.canvas.Height - 1) mouseXY.Y = this.canvas.Height - 2;            //计算矩形的位置,并进行清除,如果鼠标移动的时候不即时,那么拖动鼠标,将生成很多相同左上角、不同右下角的矩形,他们会叠加在一起
                Rectangle lastRect = Function.PointsToRectangle(startPoint, lastPoint);
                
                Rectangle lastOutlineRect = lastRect;
                //x和y放大2单位,估计是因为矩形边距的宽度
                lastOutlineRect.Inflate(2, 2);            Rectangle lastInteriorRect = lastRect;
                //恢复初始
                lastInteriorRect.Inflate(-2, -2);            Region invalidRegion = new Region(lastOutlineRect);
                invalidRegion.Xor(lastInteriorRect);            this.canvas.Invalidate(invalidRegion);
                //在获得画布的Image上面,根据上一步矩形的lastOutlineRect和lastInteriorRect,来重新绘制图片
                this.gImage.DrawImage((Bitmap)this.srcImage.Clone(), lastOutlineRect, lastOutlineRect, GraphicsUnit.Pixel);            // 根据startPoint和mouseXY这两个点的位置,构造一个矩形表达式
                Rectangle rect = Function.PointsToRectangle(startPoint, mouseXY);
                this.gSurface.DrawRectangle(pen, rect);            //根据rect这个矩形结构表达式,绘制一个矩形
                this.gImage.DrawRectangle(pen, rect);            //随着鼠标的移到,不断的更新lastPoint的值,在矩形左上角的点不变的基础上,不断变化矩形右下角的点
                lastPoint = mouseXY;
            }
        }
      

  5.   

    //根据lastOutlineRect和lastInteriorRect计算交集
    Region invalidRegion = new Region(lastOutlineRect);
    invalidRegion.Xor(lastInteriorRect);