C#利用反射实现winform中图片-移动和缩放的功能

最近在做一个项目,有个功能点是需要把图片根据鼠标滚轮的滚动放大或缩小。

然后就查资料,找到  PictureBox  控件有个鼠标滚轮的事件:

        //
        // 摘要:
        //     在控件有焦点且鼠标轮移动时发生。
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Advanced)]
        [SRCategoryAttribute("CatMouse")]
        [SRDescriptionAttribute("ControlOnMouseWheelDescr")]
        public event MouseEventHandler MouseWheel;

这个事件在控件属性面板是不显示的,因为  [Browsable(false)] 是不显示的。

事件由控件可以点出来。

pic_Show.MouseWheel += new MouseEventHandler(Pic_Show_MouseWheel);

实现功能思路:

1.鼠标按下左键,移动鼠标,图片移动,鼠标抬起,停止移动。

(这里有三个事件,按下,移动,抬起)

2.鼠标滚轮实现缩放功能。

(这里有一个事件,鼠标滚轮事件)

实例的界面布局如图:

 

下面是完整代码:

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

namespace PhotoControl
{
    public partial class FrmMain : Form
    {
        private bool IsMouseMove = false;//判断鼠标是不是在移动
        private Point MousePoint;//记录鼠标按下时的位置
        public FrmMain()
        {
            InitializeComponent();
            com_ScaleValue.SelectedIndex = 0;//默认选择缩放值是10
            //MouseWheel事件在控件属性列表里是不可见的,但是它确实是存在的。因为可以点出来这个事件。
            pic_Show.MouseWheel += new MouseEventHandler(Pic_Show_MouseWheel);
        }
        /// <summary>
        /// 选择图片的按钮事件方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_OpenPic_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFile = new OpenFileDialog();//打开文件对话框
            if (openFile.ShowDialog() == DialogResult.OK)
            {
                txt_PicPath.Text = openFile.FileName;
                LoadPic(openFile.FileName);
            }
        }
        //把图片加载到控件上
        private void LoadPic(string picPath)
        {
            pic_Show.Image = null;//先清除图片
            pic_Show.Image = Image.FromFile(picPath);//在加载图片
        }
        //鼠标按键按下
        private void pic_Show_MouseDown(object sender, MouseEventArgs e)
        {
            if (pic_Show.Image == null)//鼠标按下先判断是否有图片,如果没有则没反应
            {
                return;
            }
            if (e.Button == MouseButtons.Left)//判断是否是鼠标左键
            {
                //鼠标按下时的位置
                MousePoint.X = Cursor.Position.X;
                MousePoint.Y = Cursor.Position.Y;
                IsMouseMove = true;//当鼠标按下时认为它要移动
                pic_Show.Focus();
            }
        }
        //鼠标移动
        private void pic_Show_MouseMove(object sender, MouseEventArgs e)
        {
            if (pic_Show.Image == null)
            {
                return;
            }
            pic_Show.Focus();//图片获取焦点
            if (IsMouseMove)
            {
                int newLocX, newLocY;  //移动新位置的x,y坐标
                int lengthX, lengthY; //x,y两个方向移动的长度

                lengthX = Cursor.Position.X - MousePoint.X;
                lengthY = Cursor.Position.Y - MousePoint.Y;

                newLocX = pic_Show.Location.X + lengthX;
                newLocY = pic_Show.Location.Y + lengthY;
                pic_Show.Location = new Point(newLocX, newLocY);

                MousePoint.X = Cursor.Position.X;
                MousePoint.Y = Cursor.Position.Y;
            }
        }
        //鼠标按键抬起
        private void pic_Show_MouseUp(object sender, MouseEventArgs e)
        {
            //如果鼠标按键抬起,就停止移动
            if (e.Button == MouseButtons.Left)
            {
                IsMouseMove = false;
            }
        }
        //鼠标滚轮
        private void Pic_Show_MouseWheel(object sender, MouseEventArgs e)
        {
            if (pic_Show.Image == null)
            {
                return;
            }
            PictureBox newPic = pic_Show;
            int x = e.Location.X;//鼠标的x
            int y = e.Location.Y;//鼠标的y
            int w = newPic.Width;//图片的宽
            int h = newPic.Height;//图片的高
            int vectorX, vectorY;//因缩放产生的位移矢量
            if (e.Delta > 0) //放大
            {
                if (newPic.Width > 650)
                {
                    return;
                }
                //放大就是增加新图的宽和高
                newPic.Width += Convert.ToInt32(com_ScaleValue.Text);
                newPic.Height += Convert.ToInt32(com_ScaleValue.Text);
                //利用反射获取新图的矩形宽高信息
                PropertyInfo pInfo = newPic.GetType().GetProperty("ImageRectangle", BindingFlags.Instance | BindingFlags.NonPublic);
                Rectangle rect = (Rectangle)pInfo.GetValue(newPic, null);
                //把放大后的宽高赋值给控件
                newPic.Width = rect.Width;
                newPic.Height = rect.Height;
            }
            if (e.Delta < 0) //缩小
            {
                //防止一直缩成负值
                if (newPic.Width < 150)
                    return;
                //缩小就是减小新图的宽和高
                newPic.Width -= Convert.ToInt32(com_ScaleValue.Text);
                newPic.Height -= Convert.ToInt32(com_ScaleValue.Text);
                //利用反射获取新图的矩形宽高信息
                PropertyInfo pInfo = newPic.GetType().GetProperty("ImageRectangle", BindingFlags.Instance |
                 BindingFlags.NonPublic);
                Rectangle rect = (Rectangle)pInfo.GetValue(newPic, null);
                //把缩小后的宽高赋值给控件
                newPic.Width = rect.Width;
                newPic.Height = rect.Height;
            }
            //因缩放产生的位移,进行补偿,实现锚点缩放的效果
            vectorX = (int)((double)x * (w - newPic.Width) / w);
            vectorY = (int)((double)y * (h - newPic.Height) / h);
            newPic.Location = new Point(newPic.Location.X + vectorX, newPic.Location.Y + vectorY);
        }
    }
}

 在这里记录一下,以便以后遇到。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

你懂的11

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

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

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

打赏作者

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

抵扣说明:

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

余额充值