【C#】Winform自定义图像控件实现滚动缩放效果、拖动显示图像
|
admin
2025年3月30日 17:26
本文热度 87
|
“ 本文描述了如何使用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 编辑过