重写PictureBox实现图片的放大缩小,类似手捏

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

namespace Photograph
{
    public partial class MyPictureBox : UserControl
    {
        private Bitmap image = null;
        /// <summary>
        /// 要显示的图像
        /// </summary>
        /// 
        public Bitmap Image
        {
            set
            {
                using (Bitmap bmpTemp = (Bitmap)value.Clone())
                {
                    if (image != null) using (image) { }
                    image = (Bitmap)bmpTemp.Clone();
                }
                fitToScreen();
            }
            get
            {
                return (Bitmap)image.Clone();
            }
        }
        /// <summary>
        /// 是否拉伸图像
        /// </summary>
        ///
        [Browsable(true), Category("IsStretch"), Description("Is Stretch")]
        public bool BIsStretch
        {
            get;
            set;
        }
        private double dZoom = 1;
        public MyPictureBox()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.DoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer, true);
            this.SuspendLayout();
            this.ResumeLayout(false);
            this.AutoScroll = true;
        }
        // Paint image
        protected override void OnPaint(PaintEventArgs e)
        {
            try
            {
                if (image != null)
                {
                    using (Bitmap imageToDraw = (Bitmap)image.Clone())
                    {
                        Graphics g = e.Graphics;
                        Rectangle rc = ClientRectangle;
                        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                        g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                        int width = (int)(this.Width * dZoom);
                        int height = (int)(this.Height * dZoom);
                        if (!BIsStretch)
                        {
                            double aspectRatio = ((double)imageToDraw.Width) / imageToDraw.Height;
                            if (width >= (int)(height * aspectRatio))
                            {
                                width = (int)(height * aspectRatio);
                            }
                            else
                            {
                                height = (int)((double)width / aspectRatio);
                            }
                        }
                        int x = (rc.Width < width) ? this.AutoScrollPosition.X : (rc.Width - width) / 2;//使图像显示在中间
                        int y = (rc.Height < height) ? this.AutoScrollPosition.Y : (rc.Height - height) / 2;
                        // draw image
                        g.DrawImage(imageToDraw, new Rectangle(x, y, width, height));
                    }
                }
            }
            finally
            {
                base.OnPaint(e);
            }
        }

        /// <summary>
        /// 按放大比列显示
        /// </summary>
        private void updateZoom()
        {
            if (image==null)
            {
                return;
            }
            int width = (int)(this.Width * dZoom);
            int height = (int)(this.Height * dZoom);
            if (!BIsStretch)
            {
                double aspectRatio = ((double)image.Width) / image.Height;
                if (width >= (int)(height * aspectRatio))
                {
                    width = (int)(height * aspectRatio);
                }
                else
                {
                    height = (int)((double)width / aspectRatio);
                }
            }
            this.AutoScrollMinSize = new Size(width, height);
            this.Invalidate();
        }
        /// <summary>
        /// 按控件大小显示
        /// </summary>
        private void fitToScreen()
        {
            if (image == null)
            {
                return;
            }
            dZoom = Math.Min((double)(this.ClientRectangle.Width) / (this.Width), (double)(this.ClientRectangle.Height) / (this.Height));
            updateZoom();
            dZoom = Math.Min((double)(this.ClientRectangle.Width) / (this.Width), (double)(this.ClientRectangle.Height) / (this.Height));
            updateZoom();
        }
        /// <summary>
        ///按图像的原始大小显示
        /// </summary>
        public void zoomToOriImgSize()
        {
            if (image == null)
            {
                return;
            }
            dZoom = Math.Min((double)(image.Width) / (this.Width), (double)(image.Height) / (this.Height));
            updateZoom();
        }
        /// <summary>
        /// 重载滚轮事件,实现用滚轮放缩
        /// </summary>
        protected override void OnMouseWheel(MouseEventArgs e)
        {
            if (image == null)
            {
                return;
            }
            double numberOfTextLinesToMove = ((double)e.Delta * SystemInformation.MouseWheelScrollLines) / 1000;
            if (dZoom + numberOfTextLinesToMove >= (Math.Min((double)(this.ClientRectangle.Width) / (this.Width), (double)(this.ClientRectangle.Height) / (this.Height))) && dZoom + numberOfTextLinesToMove <= 30.00)
            {
                dZoom += numberOfTextLinesToMove;
                updateZoom();

                if (ptMoveStart.X == 0 && ptMoveStart.Y == 0)
                {
                    this.AutoScrollPosition = this.PointToScreen(new Point(ptMoveStart.X, ptMoveStart.Y));
                }
                else
                {
                    this.AutoScrollPosition = new Point(ptCurScrollPos.X + ptImgToPnl(ptCurPosInImg).X - ptMoveStart.X, ptCurScrollPos.Y + ptImgToPnl(ptCurPosInImg).Y - ptMoveStart.Y);
                }
                ptCurScrollPos = new Point(this.HorizontalScroll.Value, this.VerticalScroll.Value);
            }
        }
        /// <summary>
        /// 根据鼠标移动的距离 移动图像 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void uctrl_ImagePro_MouseMove(object sender, MouseEventArgs e)
        {
            if (image == null)
            {
                return;
            }
            if (e.Button == MouseButtons.Left)
            {
                if ((this.HorizontalScroll.Value + ((int)((ptMoveStart.X - e.X) / 5))) <= this.HorizontalScroll.Maximum && this.HorizontalScroll.Value + ((int)((ptMoveStart.X - e.X) / 5)) >= this.HorizontalScroll.Minimum)
                {
                    this.HorizontalScroll.Value += (int)((ptMoveStart.X - e.X) / 5);
                }
                if ((this.VerticalScroll.Value + ((int)((ptMoveStart.Y - e.Y) / 5))) <= this.VerticalScroll.Maximum && this.VerticalScroll.Value + ((int)((ptMoveStart.Y - e.Y) / 5)) >= this.VerticalScroll.Minimum)
                {
                    this.VerticalScroll.Value += (int)((ptMoveStart.Y - e.Y) / 5);
                }
                this.AdjustFormScrollbars(true);
                this.Invalidate();
            }
        }

        //记录鼠标拖动的开始位置
        private Point ptMoveStart = Point.Empty;
        //记录鼠标点击时鼠标在图像上的坐标
        private Point ptCurPosInImg = Point.Empty;
        private Point ptCurScrollPos = Point.Empty;
        private void uctrl_ImagePro_MouseDown(object sender, MouseEventArgs e)
        {
            if (image == null)
            {
                return;
            }
            ptMoveStart = e.Location;
            ptCurPosInImg = ptPlToImg(e.Location);
            ptCurScrollPos = new Point(this.HorizontalScroll.Value, this.VerticalScroll.Value);
        }
        /// <summary>
        /// 获得图像上的坐标对应的控件上的坐标
        /// </summary>
        private Point ptImgToPnl(Point point)
        {
            Point desPoint = Point.Empty;
            if (image == null)
            {
                return desPoint;
            }
            Rectangle rc = this.ClientRectangle;
            int width = this.Width;
            int height = this.Height;
            if (!BIsStretch)
            {
                double aspectRatio = ((double)image.Width) / image.Height;
                if (width >= (int)(height * aspectRatio))
                {
                    width = (int)(height * aspectRatio);
                }
                else
                {
                    height = (int)((double)width / aspectRatio);
                }
            }
            width = (int)(width * dZoom);
            height = (int)(height * dZoom);
            int x = (rc.Width < width) ? this.AutoScrollPosition.X : (rc.Width - width) / 2;
            int y = (rc.Height < height) ? this.AutoScrollPosition.Y : (rc.Height - height) / 2;
            desPoint = new Point((int)(point.X * dZoom) + x, (int)(point.Y * dZoom) + y);
            return desPoint;
        }
        /// <summary>
        /// 获得控件上的坐标对应到图像上的坐标
        /// </summary>
        private Point ptPlToImg(Point point)
        {
            Point desPoint = Point.Empty;
            if (image == null)
            {
                return desPoint;
            }
            Rectangle rc = this.ClientRectangle;
            int width = this.Width;
            int height = this.Height;
            if (!BIsStretch)
            {
                double aspectRatio = ((double)image.Width) / image.Height;
                if (width >= (int)(height * aspectRatio))
                {
                    width = (int)(height * aspectRatio);
                }
                else
                {
                    height = (int)((double)width / aspectRatio);
                }
            }
            width = (int)(width * dZoom);
            height = (int)(height * dZoom);
            int x = (rc.Width < width) ? this.AutoScrollPosition.X : (rc.Width - width) / 2;
            int y = (rc.Height < height) ? this.AutoScrollPosition.Y : (rc.Height - height) / 2;
            if ((point.X >= x) && (point.Y >= y) && (point.X < x + width) && (point.Y < y + height))
            {
                desPoint = new Point((int)(((double)(point.X - x)) / dZoom), (int)((double)((point.Y - y)) / dZoom));
            }
            else
            {
                desPoint = Point.Empty;
            }
            return desPoint;
        }
        /// <summary>
        ///  拦截Esc键  实现按控件界面大小显示
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void uctrl_ImagePro_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Escape)
            {
                fitToScreen();
            }
        }
        /// <summary>
        /// 双击恢复原始大小
        /// </summary>
        private void uctrl_ImagePro_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            // zoomToOriImgSize();
            fitToScreen();
        }
    }
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fanwenhu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值