using System; using System.Collections.Generic; using System.Drawing.Drawing2D; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Diagnostics; using static System.Net.Mime.MediaTypeNames; namespace LB_VisionControl { public class UserPictureBox : PictureBox, IDisposable { public UserPictureBox(Control parent) { Point location = Point.Empty; Size size = parent.ClientSize; _zoomMatrix = new Matrix(); _rect = new Rectangle(0, 0, size.Width, size.Height); this.Location = location; this.Size = size; this.SizeMode = PictureBoxSizeMode.Zoom; this.parent = parent; RegisterEvent(); } #region 变量 Control parent { get; set; } private Bitmap _currentImage = null; private readonly object _syncLock = new object(); public Bitmap Image { get => _currentImage; set { //// 根据首先设置的图像大小来计算缩放比例 //try //{ // if (_currentImage == null) // { // _imgWidth = value.Width; // _imgHeight = value.Height; // // 计算自适应缩放比例 // float zoomX = (float)parent.ClientSize.Width / _imgWidth; // float zoomY = (float)parent.ClientSize.Height / _imgHeight; // _zoom = Math.Min(zoomX, zoomY); // 取较小的比例保证完全显示 // } //} //catch { } lock (_syncLock) { try { // 释放现有资源 DisposeCurrentImage(); if (value != null) { // 创建新图像副本 //_currentImage = new Bitmap(value); SetBackImage(value); } Refresh(); } catch (Exception ex) { // 记录错误或处理异常 Debug.WriteLine($"【{DateTime.Now:HH:mm:ss.fff}】图像设置失败: {ex.Message}"); DisposeCurrentImage(); } } } } private void DisposeCurrentImage() { try { if (_tBrush != null) { _tBrush.Dispose(); _tBrush = null; } if (_currentImage != null) { _currentImage.Dispose(); _currentImage = null; } } catch { } } /// /// 用于内部激活是否重绘 /// private bool _mEnable = true; /// /// 背景纹理画刷(设置图像后会将图像转换成纹理画刷,因为填充画刷的速度要比绘制图像的速度快得多) /// private TextureBrush _tBrush; /// /// 控件的矩形区域 /// private Rectangle _rect = new Rectangle(); /// /// 图像宽度 /// private int _imgWidth = 1; /// /// 图像高度 /// private int _imgHeight = 1; /// /// 按下平移键,鼠标在控件上的横坐标 /// private float _mouseDownX = 0.0f; /// /// 按下平移键,鼠标在控件上的纵坐标 /// private float _mouseDownY = 0.0f; /// /// 缩放系数 /// private float _zoom = 1.0f; /// /// 图片左上角X轴的偏移量 /// private float _imgX = 0.0f; /// /// 图片左上角Y轴的偏移量 /// private float _imgY = 0.0f; /// /// 按下平移键,记录当前的_imgX /// private float _imgStartX = 0.0f; /// /// 按下平移键,记录当前的_imgY /// private float _imgStartY = 0.0f; /// /// 当前的缩放矩阵 /// private Matrix _zoomMatrix = new Matrix(); /// /// 最小缩放倍率 /// private float _minZoom = 0.05f; /// /// 最大缩放倍率 /// private float _maxZoom = 50.0f; /// /// 每次鼠标滚轮时,缩放系数的增量值 /// private float _mouseZoomDV = 0.05f; /// /// 平移按键 /// private MouseButtons _translateBtn = MouseButtons.Left; /// /// 指示是否正在执行平移操作 /// private bool _inTranslate = false; #endregion #region 属性 /// /// 获取是否正在执行平移操作 /// public bool InTranslate { get { return _inTranslate; } protected set { if (value != _inTranslate) { _inTranslate = value; if (value) { OnStartTranslate(); } else { OnStopTranslate(); } } } } #endregion #region 方法 /// /// 注册事件 /// public void RegisterEvent() { //this.MouseDoubleClick += new MouseEventHandler(_ctrl_MouseDoubleClick); this.MouseDown += new MouseEventHandler(_ctrl_MouseDown); this.MouseMove += new MouseEventHandler(_ctrl_MouseMove); this.MouseUp += new MouseEventHandler(_ctrl_MouseUp); this.MouseEnter += new EventHandler(_ctrl_MouseEnter); this.MouseWheel += new MouseEventHandler(_ctrl_MouseWheel); this.Paint += new PaintEventHandler(_ctrl_Paint); this.MouseDoubleClick += new MouseEventHandler(_ctrl_MouseDoubleDown); } /// /// 释放背景纹理画刷 /// protected virtual void tBrushDispose() { if (_tBrush != null) { _tBrush.Dispose(); _tBrush = null; } } /// /// 释放资源 /// public new void Dispose() { tBrushDispose(); if (_zoomMatrix != null) { _zoomMatrix.Dispose(); _zoomMatrix = null; } if (this != null) base.Dispose(); } /// /// 设置背景图像 /// /// public void SetBackImage(Bitmap img) { _mEnable = false; tBrushDispose(); //释放当前纹理 if (img != null) { _imgWidth = img.Width; _imgHeight = img.Height; //当图像的水平分辨率和垂直分辨率不为96时,将图像转换成纹理画刷之后会导致图像自动被裁剪掉一部分 if (img.VerticalResolution != 96 || img.HorizontalResolution != 96) { //重新实例化一张图片之后,新图片的水平分辨率和垂直分辨率会自动调整为96 using (Bitmap bmp = new Bitmap(img)) { _tBrush = new TextureBrush(img, WrapMode.Clamp); } } else _tBrush = new TextureBrush(img, WrapMode.Clamp); } else { _imgWidth = 1; _imgHeight = 1; } NormalMatrix(); _mEnable = true; ZoomImage(parent.ClientSize.Height / 2, parent.ClientSize.Width / 2, _zoom); } /// /// 缩放图像 /// /// 缩放的中心点X /// 缩放的中心点Y /// 缩放系数 protected void ZoomImage(int x, int y, float zoom) { if (zoom >= _maxZoom) zoom = _maxZoom; else if (zoom < _minZoom) zoom = _minZoom; float oldX = x / _zoom; float oldY = y / _zoom; _zoom = zoom; _imgX = x / zoom - oldX + _imgX; _imgY = y / zoom - oldY + _imgY; _zoomMatrix.Reset(); _zoomMatrix.Scale(zoom, zoom); _zoomMatrix.Translate(_imgX, _imgY); this.Refresh(); } /// /// 归一化当前矩阵 /// protected virtual void NormalMatrix() { //_zoom = 1.0f; //_imgX = 0.0f; //_imgY = 0.0f; //_zoomMatrix.Reset(); //_zoomMatrix.Scale(_zoom, _zoom); //_zoomMatrix.Translate(_imgX, _imgY); _zoomMatrix = new Matrix(); } #endregion #region 控件事件 private void _ctrl_Paint(object sender, PaintEventArgs e) { if (_mEnable) { Graphics g = e.Graphics; g.InterpolationMode = InterpolationMode.HighQualityBicubic; //设置插值模式 if (_tBrush != null) { g.Transform = _zoomMatrix; //设置变换矩阵 g.FillRectangle(_tBrush, 0, 0, _imgWidth, _imgHeight); } } } private void _ctrl_MouseWheel(object sender, MouseEventArgs e) { if (_mEnable) { if (e.Delta >= 0) ZoomImage(e.X, e.Y, _zoom + _mouseZoomDV); else ZoomImage(e.X, e.Y, _zoom - _mouseZoomDV); } } private void _ctrl_MouseEnter(object sender, EventArgs e) { //为控件设置焦点,因为只有控件有焦点才能为控件触发鼠标滚轮事件 this.Focus(); } private void _ctrl_MouseUp(object sender, MouseEventArgs e) { if (_mEnable) { if (e.Button == _translateBtn) { InTranslate = false; } } } private void _ctrl_MouseMove(object sender, MouseEventArgs e) { if (_mEnable) { if (_inTranslate) { float deltaX = e.X - _mouseDownX; float deltaY = e.Y - _mouseDownY; _imgX = _imgStartX + (deltaX / _zoom); _imgY = _imgStartY + (deltaY / _zoom); _zoomMatrix.Reset(); _zoomMatrix.Scale(_zoom, _zoom); _zoomMatrix.Translate(_imgX, _imgY); this.Refresh(); } } } private void _ctrl_MouseDoubleDown(object sender, MouseEventArgs e) { if (_mEnable && _currentImage != null) { Bitmap Image = _currentImage.Clone() as Bitmap; DisposeCurrentImage(); this.Image = Image; } } private void _ctrl_MouseDown(object sender, MouseEventArgs e) { if (_mEnable) { if (e.Button == _translateBtn) { _mouseDownX = e.X; _mouseDownY = e.Y; _imgStartX = _imgX; _imgStartY = _imgY; InTranslate = true; } } } //private void _ctrl_MouseDoubleClick(object sender, MouseEventArgs e) //{ // this.BeginInvoke(new Action(() => // { // try // { // // 将 Image 保存为临时文件 // string tempFilePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".jpg"); // this.Image.Save(tempFilePath, System.Drawing.Imaging.ImageFormat.Jpeg); // // 使用默认图片查看器打开临时图片 // Process.Start(tempFilePath); // Thread.Sleep(1000); // // 在操作系统打开图片后,你可以选择删除临时文件(可选) // File.Delete(tempFilePath); // 如果希望在打开后删除临时文件,取消注释此行 // } // catch { } // })); //} #endregion #region 自定义事件 /// /// 在开始平移时发生 /// public event EventHandler StartTranslate; /// /// 在结束平移时发生 /// public event EventHandler StopTranslate; /// /// 触发开始平移事件 /// protected virtual void OnStartTranslate() { if (StartTranslate != null) { StartTranslate(this, EventArgs.Empty); } } /// /// 触发结束平移事件 /// protected virtual void OnStopTranslate() { if (StopTranslate != null) { StopTranslate(this, EventArgs.Empty); } } #endregion } }