using System; using System.Drawing; using System.Windows.Forms; namespace ProductionControl.UIExtend { public struct ProTransformation { public Point Translation { get { return _translation; } } public double Scale { get { return _scale; } } private readonly Point _translation; private readonly double _scale; public ProTransformation(Point translation, double scale) { _translation = translation; _scale = scale; } public Point ConvertToIm(Point p) { return new Point((int)(p.X * _scale + _translation.X), (int)(p.Y * _scale + _translation.Y)); } public Size ConvertToIm(Size p) { return new Size((int)(p.Width * _scale), (int)(p.Height * _scale)); } public Rectangle ConvertToIm(Rectangle r) { return new Rectangle(ConvertToIm(r.Location), ConvertToIm(r.Size)); } public Point ConvertToPb(Point p) { return new Point((int)((p.X - _translation.X) / _scale), (int)((p.Y - _translation.Y) / _scale)); } public Size ConvertToPb(Size p) { return new Size((int)(p.Width / _scale), (int)(p.Height / _scale)); } public Rectangle ConvertToPb(Rectangle r) { return new Rectangle(ConvertToPb(r.Location), ConvertToPb(r.Size)); } public ProTransformation SetTranslate(Point p) { return new ProTransformation(p, _scale); } public ProTransformation AddTranslate(Point p) { return SetTranslate(new Point(p.X + _translation.X, p.Y + _translation.Y)); } public ProTransformation SetScale(double scale) { return new ProTransformation(_translation, scale); } } public class ProPictureBox : PictureBox { private Point? _clickedPoint; private ProTransformation _transformation; public ProTransformation Transformation { set { _transformation = FixTranslation(value); Invalidate(); } get { return _transformation; } } public ProPictureBox() { _transformation = new ProTransformation(new Point(1000, 0), 0.5f); MouseDown += OnMouseDown; MouseMove += OnMouseMove; MouseUp += OnMouseUp; MouseWheel += OnMouseWheel; Resize += OnResize; } private ProTransformation FixTranslation(ProTransformation value) { var maxScale = Math.Max((double)Image.Width / ClientRectangle.Width, (double)Image.Height / ClientRectangle.Height); if (value.Scale > maxScale) value = value.SetScale(maxScale); if (value.Scale < 0.3) value = value.SetScale(0.3); var rectSize = value.ConvertToIm(ClientRectangle.Size); var max = new Size(Image.Width - rectSize.Width, Image.Height - rectSize.Height); value = value.SetTranslate((new Point(Math.Min(value.Translation.X, max.Width), Math.Min(value.Translation.Y, max.Height)))); if (value.Translation.X < 0 || value.Translation.Y < 0) { value = value.SetTranslate(new Point(Math.Max(value.Translation.X, 0), Math.Max(value.Translation.Y, 0))); } return value; } private void OnResize(object sender, EventArgs eventArgs) { if (Image == null) return; Transformation = Transformation; } private void OnMouseWheel(object sender, MouseEventArgs e) { var transformation = _transformation; var pos1 = transformation.ConvertToIm(e.Location); if (e.Delta > 0) transformation = (transformation.SetScale(Transformation.Scale / 1.25)); else transformation = (transformation.SetScale(Transformation.Scale * 1.25)); var pos2 = transformation.ConvertToIm(e.Location); transformation = transformation.AddTranslate(pos1 - (Size)pos2); Transformation = transformation; } private void OnMouseUp(object sender, MouseEventArgs mouseEventArgs) { _clickedPoint = null; } private void OnMouseMove(object sender, MouseEventArgs e) { if (_clickedPoint == null) return; var p = _transformation.ConvertToIm((Size)e.Location); Transformation = _transformation.SetTranslate(_clickedPoint.Value - p); } private void OnMouseDown(object sender, MouseEventArgs e) { Focus(); _clickedPoint = _transformation.ConvertToIm(e.Location); } protected override void OnPaint(PaintEventArgs e) { var imRect = Transformation.ConvertToIm(ClientRectangle); e.Graphics.DrawImage(Image, ClientRectangle, imRect, GraphicsUnit.Pixel); } public void DecideInitialTransformation() { Transformation = new ProTransformation(Point.Empty, int.MaxValue); } } }