winform的扩展的带有截图功能picturebox

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;

namespace Aping.Common.Windows.Forms
{
    public partial class CutImageBox : System.Windows.Forms.PictureBox
    {
        public CutImageBox()
        {
            InitializeComponent();
        }

        public CutImageBox(IContainer container)
        {
            container.Add(this);

            InitializeComponent();
        }

        //自定义裁图控件
        //线条颜色
        #region 字段
        private Color borderColor = Color.Red;//线条颜色
        private bool canResize = true;//是否能够改变截图框的大小
        private int side = 6;//小框框的大小
        private int alpha = 50;//遮罩层透明度
        private bool showCutArea = true;//是否展示截图框
        private Rectangle CutImageArea = new Rectangle(5, 5, 120, 160);
        private Rectangle[] Lites = new Rectangle[8];
        private AreaAlign cutAreaAlign = AreaAlign.Default;
        private int miniWidth = 120;//最小宽
        private int miniHeight = 160;//最小高
        private bool ownerDraw = false;
        private bool autoHide = false;
        private System.Drawing.Drawing2D.DashStyle dashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
        #endregion

        #region 属性
        [Description("设置截图框边框的颜色。")]
        public Color AreaBoderColor { get { return borderColor; } set { borderColor = value; Invalidate(); } }
        [Description("是否可以改变截图框的大小。")]
        public bool EnableResize { get { return canResize; } set { canResize = value; } }
        //小方框的大小        
        [Description("是否显示截图框,默认为显示。")]
        public bool ShowCutArea { get { return showCutArea; } set { showCutArea = value; Invalidate(); } }
        [Description("截图框的透明度,默认值:50。")]
        public int AreaAlpha { get { return alpha; } set { alpha = value; Invalidate(); } }
        [Description("截图框加载后显示的位置,默认为左上角。")]
        public AreaAlign CutAreaAlign
        {
            get { return cutAreaAlign; }
            set
            {
                cutAreaAlign = value;
                switch (cutAreaAlign)
                {
                    case AreaAlign.Default:
                        CutImageArea = new Rectangle(15, 15, miniWidth, miniHeight);
                        break;
                    case AreaAlign.Center:
                        CutImageArea = new Rectangle((Width - miniWidth) / 2, (Height - miniHeight) / 2, miniWidth, miniHeight);
                        break;
                    case AreaAlign.RightCenter:
                        CutImageArea = new Rectangle(Width - CutImageArea.Width - 15, (Height - miniHeight) / 2, miniWidth, miniHeight);
                        break;
                    case AreaAlign.RightTop:
                        CutImageArea = new Rectangle(Width - CutImageArea.Width - 15, 15, miniWidth, miniHeight);
                        break;
                    case AreaAlign.LeftCenter:
                        CutImageArea = new Rectangle(15, (Height - miniHeight) / 2, miniWidth, miniHeight);
                        break;
                    case AreaAlign.LeftBottom:
                        CutImageArea = new Rectangle(15, Height - CutImageArea.Width - 15, miniWidth, miniHeight);
                        break;
                    case AreaAlign.RightBottom:
                        CutImageArea = new Rectangle(Width - CutImageArea.Width - 15, Height - CutImageArea.Width - 15, miniWidth, miniHeight);
                        break;
                    default:
                        break;
                }
                Invalidate();
            }
        }
        [Description("截图框宽的最小值,默认值:120。")]
        public int MiniWidth { get { return miniWidth; } set { miniWidth = value; } }
        [Description("截图框高的最小值,默认值:160。")]
        public int MiniHeight { get { return miniHeight; } set { miniHeight = value; } }
        [Description("开启手动绘图,EnableResize 必须开启。")]
        public bool EnableOwnerDraw { get { return ownerDraw && canResize; } set { ownerDraw = value; Invalidate(); } }
        [Description("是否在截完图后自动隐藏。")]
        public bool AutoHide { get { return autoHide; } set { autoHide = value; } }
        [Description("绘图框边框的样式,不要使用customs。")]
        public System.Drawing.Drawing2D.DashStyle AreaBorder { get { return dashStyle; } set { if (value != System.Drawing.Drawing2D.DashStyle.Custom)dashStyle = value; Invalidate(); } }
        #endregion

        #region 参数
        private Point MouseDownPoint;
        private Point MouseDownPointToScreen;
        private Point CutImageAreaLocationToScreen;
        private Point CutImageOldLocation;
        private Size OldCutImageAreaSize;
        private MouseDirection mouseDirection = MouseDirection.NONE;
        private System.Drawing.Point RectStartPoint;
        private System.Drawing.Point RectEndPoint;

        #endregion

        #region 方法
        /// <summary>
        /// 判断某个点是否在指定的区域内
        /// </summary>
        /// <param name="leftup">左上角的点</param>
        /// <param name="rightdown">右下角的点</param>
        /// <param name="compare">需要判断的点</param>
        /// <returns>
        ///     是 :true 否 false
        /// </returns>
        private bool IsInArea(Point leftup, Point rightdown, Point compare)
        {
            if (compare.X > leftup.X && compare.Y > leftup.Y && compare.X < rightdown.X && compare.Y < rightdown.Y)
            {
                return true;
            }
            return false;
        }
        /// <summary>
        /// 判断某个点是否在指定的区域内
        /// </summary>
        /// <param name="leftup">左上角的点</param>
        /// <param name="width">区域宽</param>
        /// <param name="height">区域高</param>
        /// <param name="compare">需要判断的点</param>
        /// <returns>
        ///     是 :true 否 false
        /// </returns>
        private bool IsInArea(Point leftup, int width, int height, Point compare)
        {
            if (compare.X > leftup.X && compare.Y > leftup.Y && compare.X < leftup.X + width && compare.Y < leftup.Y + height)
            {
                return true;
            }
            return false;
        }
        //图像裁剪
        public Bitmap GetPartOfImage(Bitmap sourceImg, int width, int height, int offsetX, int offsetY)
        {
            Bitmap sourceBitmap = sourceImg;

            Bitmap resultBitmap = new Bitmap(width, height);
            using (Graphics g = Graphics.FromImage(resultBitmap))
            {
                Rectangle resultRectangle = new Rectangle(0, 0, width, height);
                Rectangle sourceRectangle = new Rectangle(0 + offsetX, 0 + offsetY, width, height);

                //万能的drawImage函数啊,七七八八的参数非常多 普通的图片拉伸 放大 等效果都可以用它来做到。
                //第一个参数:原图(被裁剪的图)
                //第二个参数:目标Image(裁剪后的图)
                //第三个参数:原图被裁剪的区域
                //第四个参数:单位(当然是像素啦)
                g.DrawImage(sourceBitmap, resultRectangle, sourceRectangle, GraphicsUnit.Pixel);
            }
            return resultBitmap;
        }
        bool CanMove()
        {
            bool flag = true;
            if (CutImageArea.Width >= Width)
                flag = false;
            if (CutImageArea.Height >= Height)
                flag = false;
            if (CutImageArea.Width <= MiniWidth)
                flag = false;
            if (CutImageArea.Height <= MiniHeight)
                flag = false;
            return flag;
        }
        #endregion

        #region 重写的方法
        protected override void OnMouseDoubleClick(MouseEventArgs e)
        {
            base.OnMouseDoubleClick(e);
            if (Image == null)
                throw new ArgumentNullException("aping extends control throws exception error message : image is null");
            //处理裁图
            Bitmap cutted = GetPartOfImage((Bitmap)Image, CutImageArea.Width, CutImageArea.Height, CutImageArea.X, CutImageArea.Y);
            Image = cutted;
            if (autoHide)
            {
                Lites = new Rectangle[8];
                showCutArea = false;
                Invalidate();
            }
            if (OnCuttedImage != null)
                OnCuttedImage(Image);
        }
        protected override void CreateHandle()
        {
            base.CreateHandle();
        }
        protected override void OnLoadCompleted(AsyncCompletedEventArgs e)
        {
            base.OnLoadCompleted(e);

        }
        protected override void OnMouseWheel(MouseEventArgs e)
        {
            base.OnMouseWheel(e);
        }
        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);
            if (e.KeyCode == Keys.Up)
                CutImageArea.Location = new Point(CutImageOldLocation.X, CutImageOldLocation.Y + 5);
        }
        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            mouseDirection = MouseDirection.NONE;
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);



            if (mouseDirection != MouseDirection.NONE && mouseDirection != MouseDirection.ALL)
            {
                DoResponse(e);
                return;
            }
            // 
            /*   N
             * W   E
             *   S
             * */
            Point epoint = e.Location;
            #region 改变鼠标样式

            if (IsInArea(new Point(Lites[0].X + side, Lites[0].Y + side), Lites[4].Location, epoint))
            { Cursor = Cursors.SizeAll; }
            else if (IsInArea(Lites[0].Location, side, side, epoint))
            { Cursor = Cursors.SizeNWSE; }
            else if (IsInArea(Lites[4].Location, side, side, epoint))
            { Cursor = Cursors.SizeNWSE; }
            else if (IsInArea(Lites[1].Location, side, side, epoint))
            { Cursor = Cursors.SizeNS; }
            else if (IsInArea(Lites[5].Location, side, side, epoint))
            { Cursor = Cursors.SizeNS; }
            else if (IsInArea(Lites[2].Location, side, side, epoint))
            { Cursor = Cursors.SizeNESW; }
            else if (IsInArea(Lites[6].Location, side, side, epoint))
            { Cursor = Cursors.SizeNESW; }
            else if (IsInArea(Lites[3].Location, side, side, epoint))
            { Cursor = Cursors.SizeWE; }
            else if (IsInArea(Lites[7].Location, side, side, epoint))
            { Cursor = Cursors.SizeWE; }
            else
            { Cursor = Cursors.Default; }

            #endregion
            //当鼠标左键按下去了
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                //在可拖动的区域内
                if (IsInArea(new Point(Lites[0].X + side, Lites[0].Y + side), Lites[4].Location, epoint))
                { mouseDirection = MouseDirection.ALL; }
                else if (IsInArea(Lites[0].Location, side, side, epoint))//
                { mouseDirection = MouseDirection.NW; }
                else if (IsInArea(Lites[4].Location, side, side, epoint))//
                { mouseDirection = MouseDirection.SE; }
                else if (IsInArea(Lites[1].Location, side, side, epoint))//
                { mouseDirection = MouseDirection.N; }
                else if (IsInArea(Lites[5].Location, side, side, epoint))//
                { mouseDirection = MouseDirection.S; }
                else if (IsInArea(Lites[2].Location, side, side, epoint))//
                { mouseDirection = MouseDirection.NE; }
                else if (IsInArea(Lites[6].Location, side, side, epoint))//
                { mouseDirection = MouseDirection.SW; }
                else if (IsInArea(Lites[3].Location, side, side, epoint))//
                { mouseDirection = MouseDirection.E; }
                else if (IsInArea(Lites[7].Location, side, side, epoint))//
                { mouseDirection = MouseDirection.W; }
                else
                { mouseDirection = MouseDirection.NONE; }

                if (mouseDirection != MouseDirection.NONE && mouseDirection != MouseDirection.ALL)
                    DoResponse(e);
                if (mouseDirection == MouseDirection.ALL)
                {
                    Point l = CutImageOldLocation;
                    Point epointToScreen = PointToScreen(e.Location);
                    l.Offset(epointToScreen.X - MouseDownPointToScreen.X, epointToScreen.Y - MouseDownPointToScreen.Y);
                    CutImageArea.Location = l;
                    //
                    if (CutImageArea.Location.X <= (side / 2 + 1))
                        CutImageArea.Location = new Point((side / 2) + 1, CutImageArea.Location.Y);
                    if (CutImageArea.Y <= (side / 2 + 1))
                        CutImageArea.Location = new Point(CutImageArea.Location.X, (side / 2) + 1);
                    if (CutImageArea.Location.X >= Width - CutImageArea.Width - (side / 2 + 1))
                        CutImageArea.Location = new Point(Width - CutImageArea.Width - (side / 2 + 1), CutImageArea.Location.Y);
                    if (CutImageArea.Location.Y >= Height - CutImageArea.Height - (side / 2 + 1))
                        CutImageArea.Location = new Point(CutImageArea.Location.X, Height - CutImageArea.Height - (side / 2 + 1));
                }
                Invalidate();
            }
            else if (e.Button == System.Windows.Forms.MouseButtons.Right && ownerDraw)
            {
                RectEndPoint = e.Location;
                CutImageArea = new System.Drawing.Rectangle(RectStartPoint, new System.Drawing.Size(e.X - RectStartPoint.X, e.Y - RectStartPoint.Y));
                Invalidate();
            }
        }
        void DoResponse(MouseEventArgs e)
        {
            if (!canResize)
                return;
            Point epointToScreen = PointToScreen(e.Location);
            Point l = CutImageOldLocation;

            l.Offset(epointToScreen.X - this.MouseDownPointToScreen.X, epointToScreen.Y - this.MouseDownPointToScreen.Y);

            switch (mouseDirection)
            {
                case MouseDirection.N:
                    if (CanMove())
                        CutImageArea.Location = new Point(CutImageOldLocation.X, l.Y);
                    CutImageArea.Height = OldCutImageAreaSize.Height - (epointToScreen.Y - MouseDownPointToScreen.Y);

                    break;
                case MouseDirection.S:
                    CutImageArea.Height = OldCutImageAreaSize.Height + (epointToScreen.Y - MouseDownPointToScreen.Y);
                    break;
                case MouseDirection.W:
                    CutImageArea.Width = OldCutImageAreaSize.Width - (epointToScreen.X - MouseDownPointToScreen.X);
                    if (CanMove())
                        CutImageArea.Location = new Point(l.X, CutImageOldLocation.Y);
                    break;
                case MouseDirection.E:
                    CutImageArea.Width = OldCutImageAreaSize.Width + (epointToScreen.X - MouseDownPointToScreen.X);
                    break;
                case MouseDirection.NE:
                    CutImageArea.Width = OldCutImageAreaSize.Width + (epointToScreen.X - MouseDownPointToScreen.X);
                    CutImageArea.Height = OldCutImageAreaSize.Height - (epointToScreen.Y - MouseDownPointToScreen.Y);
                    if (CanMove())
                        CutImageArea.Location = new Point(CutImageOldLocation.X, l.Y);
                    break;
                case MouseDirection.SW:
                    CutImageArea.Width = OldCutImageAreaSize.Width - (epointToScreen.X - MouseDownPointToScreen.X);
                    CutImageArea.Height = OldCutImageAreaSize.Height + (epointToScreen.Y - MouseDownPointToScreen.Y);
                    if (CanMove())
                        CutImageArea.Location = new Point(l.X, CutImageOldLocation.Y);
                    break;
                case MouseDirection.NW:
                    CutImageArea.Width = OldCutImageAreaSize.Width - (epointToScreen.X - MouseDownPointToScreen.X);
                    CutImageArea.Height = OldCutImageAreaSize.Height - (epointToScreen.Y - MouseDownPointToScreen.Y);
                    if (CanMove())
                        CutImageArea.Location = new Point(l.X, l.Y);
                    break;
                case MouseDirection.SE:
                    CutImageArea.Width = OldCutImageAreaSize.Width + (epointToScreen.X - MouseDownPointToScreen.X);
                    CutImageArea.Height = OldCutImageAreaSize.Height + (epointToScreen.Y - MouseDownPointToScreen.Y);
                    CutImageArea.Location = new Point(CutImageOldLocation.X, CutImageOldLocation.Y);
                    break;
                case MouseDirection.ALL:
                    break;
                case MouseDirection.NONE:
                    break;
                default:
                    break;
            }

            if (CutImageArea.Width >= Width)
                CutImageArea.Width = Width - side - 1;
            if (CutImageArea.Height >= Height)
                CutImageArea.Height = Height - side - 1;
            if (CutImageArea.Width <= MiniWidth)
                CutImageArea.Width = MiniWidth;
            if (CutImageArea.Height <= MiniHeight)
                CutImageArea.Height = MiniHeight;
            Invalidate();
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            CutImageOldLocation = CutImageArea.Location;
            CutImageAreaLocationToScreen = PointToScreen(CutImageArea.Location);
            MouseDownPoint = e.Location;
            MouseDownPointToScreen = PointToScreen(e.Location);
            OldCutImageAreaSize = CutImageArea.Size;
            if (ownerDraw && e.Button == System.Windows.Forms.MouseButtons.Right)
            {
                //右键自己绘制截图框
                RectStartPoint = e.Location;
            }
        }
        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);
            if (showCutArea)
            {
                /*  0 1 2
                 *  7   3
                 *  6 5 4
                 */
                //左上角 0
                Lites[0] = new Rectangle(CutImageArea.Left - side / 2, CutImageArea.Top - side / 2, side, side);
                //上中 1
                Lites[1] = new Rectangle(CutImageArea.Left + (CutImageArea.Width - side) / 2, CutImageArea.Top - side / 2, side, side);
                //右上角 2
                Lites[2] = new Rectangle(CutImageArea.Width + CutImageArea.Left - side / 2, CutImageArea.Top - side / 2, side, side);
                //右中 3
                Lites[3] = new Rectangle(CutImageArea.Width + CutImageArea.Left - side / 2, CutImageArea.Top + (CutImageArea.Height - side) / 2, side, side);
                //右下角 4
                Lites[4] = new Rectangle(CutImageArea.Width + CutImageArea.Left - side / 2, CutImageArea.Top + CutImageArea.Height - side / 2, side, side);
                //下中 5 
                Lites[5] = new Rectangle(CutImageArea.Left + (CutImageArea.Width - side) / 2, CutImageArea.Top + CutImageArea.Height - side / 2, side, side);
                //下中 6 
                Lites[6] = new Rectangle(CutImageArea.Left - side / 2, CutImageArea.Top + CutImageArea.Height - side / 2, side, side);
                //下中 7 
                Lites[7] = new Rectangle(CutImageArea.Left - side / 2, CutImageArea.Top + (CutImageArea.Height - side) / 2, side, side);
                Pen pen = new Pen(new SolidBrush(borderColor));
                pen.DashStyle = dashStyle;
                pe.Graphics.DrawRectangle(pen, CutImageArea);
                pe.Graphics.DrawRectangles(pen, Lites);

                pe.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                System.Drawing.Color cor = System.Drawing.Color.FromArgb(alpha, borderColor);
                System.Drawing.SolidBrush bsh = new System.Drawing.SolidBrush(cor);
                pe.Graphics.FillRectangle(bsh, CutImageArea);
            }
        }
        #endregion

        #region 自定义事件
        public delegate void CuttedImage(Image image);
        [Description("双击截图后触发的事件")]
        public event CuttedImage OnCuttedImage;
        #endregion
        enum MouseDirection
        {
            N, S, W, E, NE, SW, NW, SE, ALL, NONE
        }
        public enum AreaAlign
        {
            Default, Center, RightCenter, RightTop, LeftCenter, LeftBottom, RightBottom
        }
    }
}
原文地址:https://www.cnblogs.com/CrazyAnts/p/3680758.html