【C#】Winform自定义图像控件实现滚动缩放效果、拖动显示图像
				
									
					
					
						|  | 
							admin 2025年3月30日 17:26
								本文热度 1697 | 
					
				 
				“ 本文描述了如何使用Winform创建用户图像控件、实现滚动缩放效果,拖动显示图像。”
前言                           
    PictureBox 是 Windows Forms (WinForms) 中的一个内置控件,专门用于在窗体上显示图像,其可以显示多种格式的图像(如:BMP、JPEG、GIF、PNG、ICO 等)。
    PictureBox 内置了如下几种图像显示方式:Normal:图像放置在控件的左上角,不缩放。
StretchImage:拉伸图像以填充控件。
AutoSize:调整控件大小以适应图像。
CenterImage:图像居中显示,不缩放。
Zoom:按比例缩放图像,保持纵横比。
    上面的图像显示方法只能实现基本的图像功能,。如果想要实现更好的体验效果。还需要自定义一些功能,下面就是自定义一个图像用户控件实现滚动鼠标缩放图像、鼠标拖动显示图像。
运行环境                     系      统:Win11
开发工具:Visual Studio 2022
相关技术:C# 、Winform .Net Framework 4.6.0
实现功能                     1、鼠标双击还原
2、鼠标滚动缩放:放大、缩小
3、点击按钮:放大、缩小、还原
4、鼠标按住拖动图像
 运行效果                     

图像控件代码
下面是自定义图像控件代码: public partial class UCPictrueBox : UserControl {     #region 字段、属性     #region 字段     private Image _image;                                private float _zoomFactor = 1.0f;                    private const float ZoomIncrement = 0.1f;            private const float MinZoom = 0.01f;                 private const float MaxZoom = 20.0f;                 private Point _lastLocation;                         private bool _isDragging = false;                    private PointF _imagePosition = PointF.Empty;        #endregion     #region 属性      [Description("获取或设置控件显示的图像。")]     [Category("UserDefine")]     public Image Image     {         get => _image;         set         {             _image = value;             _zoomFactor = 1.0f;             _imagePosition = PointF.Empty;             ImageCenter();             Invalidate();         }     }     #endregion     #endregion     #region 构造函数     public UCPictrueBox()     {         InitializeComponent();         this.DoubleBuffered = true;         this.BackColor = Color.LightGray;         this.BorderStyle = BorderStyle.FixedSingle;         this.MouseWheel += ImageZoom_MouseWheel;         this.MouseDown += ImageZoom_MouseDown;         this.MouseMove += ImageZoom_MouseMove;         this.MouseUp += ImageZoom_MouseUp;         this.MouseDoubleClick += ImageZoom_MouseDoubleClick;     }     #endregion     #region 图像操作                         private void ImageCenter()     {         if (_image == null) return;         Size scaledSize = GetScaledSize();         _imagePosition = new PointF((this.ClientSize.Width - scaledSize.Width) / 2f, (this.ClientSize.Height - scaledSize.Height) / 2f);         Invalidate();     }                    private void Zoom(float factor)     {         if (_image == null) return;                  Point mousePos = this.PointToClient(MousePosition);         Size scaledSize = GetScaledSize();         float mouseXRelative = (mousePos.X - _imagePosition.X) / scaledSize.Width;         float mouseYRelative = (mousePos.Y - _imagePosition.Y) / scaledSize.Height;                  float newZoom = _zoomFactor + factor;                  newZoom = Math.Max(MinZoom, Math.Min(MaxZoom, newZoom));                  if (Math.Abs(newZoom - _zoomFactor) > 0.01f)         {             _zoomFactor = newZoom;             Size newSize = GetScaledSize();                          _imagePosition = new PointF(mousePos.X - mouseXRelative * newSize.Width, mousePos.Y - mouseYRelative * newSize.Height);                          if (newSize.Width <= this.ClientSize.Width && newSize.Height <= this.ClientSize.Height)             {                 ImageCenter();             }             Invalidate();         }     }                    public void ZoomIn()     {         Zoom(ZoomIncrement);     }                    public void ZoomOut()     {         Zoom(-ZoomIncrement);     }                    public void ZoomReset()     {         _zoomFactor = 1.0f;         ImageCenter();     }                    private Size GetScaledSize()     {         return new Size((int)(_image.Width * _zoomFactor), (int)(_image.Height * _zoomFactor));     }     #endregion     #region 事件方法重写                    protected override void OnPaint(PaintEventArgs e)     {         base.OnPaint(e);         if (_image == null) return;         Size scaleSize = GetScaledSize();         Rectangle destRect;         if (_imagePosition == PointF.Empty)         {             int x = (this.ClientSize.Width - scaleSize.Width) / 2;             int y = (this.ClientSize.Height - scaleSize.Height) / 2;             destRect = new Rectangle(x, y, scaleSize.Width, scaleSize.Height);         }         else         {             destRect = new Rectangle(                 (int)_imagePosition.X,                 (int)_imagePosition.Y,                 scaleSize.Width,                 scaleSize.Height);         }                  e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;         e.Graphics.DrawImage(_image, destRect);     }                    protected override void OnResize(EventArgs e)     {         base.OnResize(e);         if (_image != null)         {                          Size scaledSize = GetScaledSize();             if (scaledSize.Width <= this.ClientSize.Width && scaledSize.Height <= this.ClientSize.Height)             {                 ImageCenter();             }         }     }     #endregion     #region 鼠标事件处理:滚轮缩放、按下拖拽、移动显示、松开取消拖拽、双击还原     private void ImageZoom_MouseWheel(object sender, MouseEventArgs e)     {         if (e.Delta > 0)         {             ZoomIn();         }         else if (e.Delta < 0)         {             ZoomOut();         }     }     private void ImageZoom_MouseDown(object sender, MouseEventArgs e)     {         if (e.Button == MouseButtons.Left && _image != null)         {             _lastLocation = e.Location;             _isDragging = true;             this.Cursor = Cursors.Hand;         }     }     private void ImageZoom_MouseMove(object sender, MouseEventArgs e)     {         if (_isDragging && _image != null)         {             int deltaX = e.X - _lastLocation.X;             int deltaY = e.Y - _lastLocation.Y;             _imagePosition.X += deltaX;             _imagePosition.Y += deltaY;             _lastLocation = e.Location;             Invalidate();         }     }     private void ImageZoom_MouseUp(object sender, MouseEventArgs e)     {         _isDragging = false;         this.Cursor = Cursors.Default;     }     private void ImageZoom_MouseDoubleClick(object sender, MouseEventArgs e)     {         ZoomReset();     }     #endregion }
窗体代码
    窗体代码,添加3个按钮即可。
public partial class MainForm : WinFormBase{    public MainForm()    {        InitializeComponent();        this.CenterToParent();        this.CenterToScreen();    }    private void btn_ZoomIn_Click(object sender, System.EventArgs e)    {        ucPic_Image.ZoomIn();    }    private void btn_ZoomOut_Click(object sender, System.EventArgs e)    {        ucPic_Image.ZoomOut();    }    private void btn_Reset_Click(object sender, System.EventArgs e)    {        string filePath = Application.StartupPath + "\\source.png";        ucPic_Image.Image = Image.FromFile(filePath);    }}
结语
    使用方法,将自定义控件创建在同一个命名空间下,点击生成无报错后,即可在工具箱中查看选择自定义控件。拖拽到当前窗体即可。
如果是引用自定义控件类库分类实现,引用时可能得报错原因,目标框架不同。
如果想使用图中自定义窗体请查看。
阅读原文:原文链接
该文章在 2025/3/31 11:17:09 编辑过