namespace Yw.WinFrmUI.HydroL2d { /// /// 管网面板 /// public partial class NetworkPanel : Panel { public NetworkPanel() { InitializeComponent(); #region 防止闪烁 SetStyle(ControlStyles.AllPaintingInWmPaint, true); SetStyle(ControlStyles.DoubleBuffer, true); SetStyle(ControlStyles.UserPaint, true); #endregion //设置允许的最小尺寸 this.MinimumSize = new Size(10, 10); } #region 初始化 protected Network _network = null;//管网 protected RectangleF _networkBounds;//管网边界 protected RectangleF _clientRectf;//工作区域矩形 /// /// 是否初始化 /// public bool Initialized => _network != null; /// /// 初始化 /// public virtual void Initial(Network network) { _network = network; _networkBounds = _network.GetBounds(); _clientRectf = GetClientRectangleF(); CreateCache(); ZoomAll(); } #endregion #region 缓存与显示 private Bitmap _cache = null;//缓存<依据工作区域创建的空图片> private object _cacheLocker = new();//缓存锁 /// /// 创建缓存 /// protected virtual void CreateCache() { if (!Initialized) { return; } var img = new Bitmap((int)_clientRectf.Width, (int)_clientRectf.Height); lock (_cacheLocker) { if (_cache != null) { _cache.Dispose(); } _cache = img; } } /// /// 绘制缓存 /// protected virtual void DrawCache() { if (!Initialized) { return; } if (_cache == null) { return; } var dispRect = GetDispRectangleF(); using (var g = Graphics.FromImage(_cache)) { g.Clear(Color.White); g.PageUnit = GraphicsUnit.Pixel; g.InterpolationMode = InterpolationMode.High; g.SmoothingMode = SmoothingMode.AntiAlias; g.PixelOffsetMode = PixelOffsetMode.HighQuality; g.PageScale = _zoom; g.TranslateTransform(_dxo, _dyo); g.ScaleTransform(1, -1); _network.Draw(g, dispRect); } } /// /// 应用缓存 /// protected virtual void ApplyCache(Graphics g) { if (!Initialized) { return; } lock (_cacheLocker) { if (_cache != null) { g.DrawImage(_cache, _clientRectf); } } } #endregion #region 缩放与偏移 private float _zoomMin = 0.001f;//最小缩放层级 private float _zoomMax = 30000f;//最大缩放层级 private float _zoom = 1f;//当前缩放层级 private float _dxo = 0f;//x偏移量 private float _dyo = 0f;//y偏移量 /// /// 缩放等级 /// public float Zoom { get => _zoom; private set { if (_networkBounds.IsEmpty) { _zoom = 1f; return; } float sizeMax = Math.Max(_networkBounds.Height, _networkBounds.Width); float sizeNew = sizeMax * value; if (sizeNew > _zoomMax) { _zoom = _zoomMax / sizeMax; } else if (sizeNew < _zoomMin) { _zoom = _zoomMin / sizeMax; } else { _zoom = value; } } } /// /// 自适应 /// public void ZoomAll() { if (!Initialized) { return; } var networkBounds = _network.GetBounds(); if (networkBounds.IsEmpty) { return; } this.Zoom = networkBounds.Width / networkBounds.Height < this.Width / this.Height ? this.Height / networkBounds.Height : this.Width / networkBounds.Width; _dxo = -networkBounds.X; _dyo = networkBounds.Bottom; this.Zoom *= 0.9f; _dxo += this.Width * 0.5f / this.Zoom - networkBounds.Width * 0.5f; _dyo += this.Height * 0.5f / this.Zoom - networkBounds.Height * 0.5f; } private void ZoomToPoint(MouseEventArgs e) { float scale = e.Delta > 0 ? this.Zoom * 1.5f : this.Zoom / 1.5f; var pt = ClientToDispPoint(e.Location); this.Zoom = scale; _dxo = -pt.X + e.X / this.Zoom; _dyo = pt.Y + e.Y / this.Zoom; } #endregion #region 坐标转换 protected PointF ClientToDispPoint(PointF cp) { return new PointF(-_dxo + cp.X / _zoom, _dyo - cp.Y / _zoom); } #endregion #region 边框绘制 /// /// 边框颜色 /// [Browsable(true)] [Description("自定义边框颜色")] public Color CustomBorderColor { get { return _customBorderColor; } set { _customBorderColor = value; } } private Color _customBorderColor = Color.Gray; /// /// 边框宽度 /// [Browsable(true)] [Description("自定义边框宽度")] public int CustomBorderWidth { get { return _customBorderWidth; } set { _customBorderWidth = value; } } private int _customBorderWidth = 1; /// /// 边框是否显示 /// [Browsable(true)] [Description("自定义边框可见性")] [DefaultValue(false)] public bool CustomBorderVisible { get { return _customBorderVisible; } set { _customBorderVisible = value; } } private bool _customBorderVisible = false; /// /// 绘制自定义边框 /// protected virtual void DrawCustomBorder(Graphics g) { if (this.CustomBorderVisible) { ControlPaint.DrawBorder(g, this.ClientRectangle, this.CustomBorderColor, this.CustomBorderWidth, ButtonBorderStyle.Solid, this.CustomBorderColor, this.CustomBorderWidth, ButtonBorderStyle.Solid, this.CustomBorderColor, this.CustomBorderWidth, ButtonBorderStyle.Solid, this.CustomBorderColor, this.CustomBorderWidth, ButtonBorderStyle.Solid); } } #endregion #region 获取矩形区域 /// /// 获取工作区域 /// /// protected virtual RectangleF GetClientRectangleF() { return new RectangleF(0, 0, this.Width, this.Height); } /// /// 获取显示区域 /// protected virtual RectangleF GetDispRectangleF() { if (_clientRectf.IsEmpty) { return default; } if (!Initialized) { return default; } var pt = ClientToDispPoint(new PointF(_clientRectf.X, _clientRectf.Height)); var width = _clientRectf.Width / _zoom; var height = _clientRectf.Height / _zoom; return new RectangleF(pt, new SizeF(width, height)); } #endregion #region 鼠标左键按下拖动 /// /// 当鼠标左键按下时允许拖动 /// [Browsable(true)] [Description("当鼠标左键按下时允许拖动")] [DefaultValue(true)] public bool AllowMoveWhenMouseLeftDown { get => _allowMoveWhenMouseLeftDown; set => _allowMoveWhenMouseLeftDown = value; } private bool _allowMoveWhenMouseLeftDown = true; protected bool _hasMouseLeftDown = false;//鼠标左键是否按下 protected Point _mouseLeftDownMovePoint;//鼠标左键按下移动点 /// /// 判断鼠标左键是否按下 /// protected virtual bool HasMouseLeftDown(MouseEventArgs e) { if (e.Button == MouseButtons.Left) { _hasMouseLeftDown = true; _mouseLeftDownMovePoint = e.Location; return true; } return false; } /// /// 鼠标左键按下移动 /// /// protected virtual bool MouseLeftDownMove(MouseEventArgs e) { if (_hasMouseLeftDown) { if (this.AllowMoveWhenMouseLeftDown) { if (this.Initialized) { var pt = new PointF(e.X - _mouseLeftDownMovePoint.X, e.Y - _mouseLeftDownMovePoint.Y); _dxo += pt.X / _zoom; _dyo += pt.Y / _zoom; _mouseLeftDownMovePoint = e.Location; return true; } } } return false; } /// /// 判断鼠标左键是否弹起 /// protected virtual bool HasMouseLeftUp(MouseEventArgs e) { if (_hasMouseLeftDown) { _hasMouseLeftDown = false; return true; } return false; } #endregion #region 鼠标右键按下拖动 /// /// 当鼠标右键按下时允许拖动 /// [Browsable(true)] [Description("当鼠标右键按下时允许拖动")] [DefaultValue(true)] public bool AllowMoveWhenMouseRightDown { get => _allowMoveWhenMouseRightDown; set => _allowMoveWhenMouseRightDown = value; } private bool _allowMoveWhenMouseRightDown = true; protected bool _hasMouseRightDown = false;//鼠标右键是否按下 protected Point _mouseRightDownMovePoint;//鼠标右键按下移动点 /// /// 判断鼠标右键是否按下 /// protected virtual bool HasMouseRightDown(MouseEventArgs e) { if (e.Button == MouseButtons.Right) { _hasMouseRightDown = true; _mouseRightDownMovePoint = e.Location; return true; } return false; } /// /// 鼠标右键按下移动 /// protected virtual bool MouseRightDownMove(MouseEventArgs e) { if (_hasMouseRightDown) { if (this.AllowMoveWhenMouseRightDown) { if (this.Initialized) { var pt = new PointF(e.X - _mouseRightDownMovePoint.X, e.Y - _mouseRightDownMovePoint.Y); _dxo += pt.X / _zoom; _dyo += pt.Y / _zoom; _mouseRightDownMovePoint = e.Location; return true; } } } return false; } /// /// 判断鼠标左键是否弹起 /// protected virtual bool HasMouseRightUp(MouseEventArgs e) { if (_hasMouseRightDown) { _hasMouseRightDown = false; return true; } return false; } #endregion #region 鼠标左键双击恢复自适应 /// /// 当鼠标双击时允许自适应 /// [Browsable(true)] [Description("当鼠标双击时允许自适应")] [DefaultValue(true)] public bool AllowZoomAllWhenMouseLeftDoubleClick { get => _allowZoomAllWhenMouseLeftDoubleClick; set => _allowZoomAllWhenMouseLeftDoubleClick = value; } private bool _allowZoomAllWhenMouseLeftDoubleClick = true; /// /// 鼠标双击时自适应 /// protected virtual bool ZoomAllWhenMouseLeftDoubleClick(MouseEventArgs e) { if (e.Button == MouseButtons.Left) { if (e.Clicks > 1) { if (this.AllowZoomAllWhenMouseLeftDoubleClick) { if (this.Initialized) { ZoomAll(); return true; } } } } return false; } #endregion #region 鼠标悬停 /// /// 允许鼠标悬停 /// [Browsable(true)] [Description("允许鼠标悬停")] [DefaultValue(true)] public bool AllowMouseHover { get => _allowMouseHover; set => _allowMouseHover = value; } private bool _allowMouseHover = true; private List _lastHoverList = null;//最后一次悬停列表 /// /// 悬停 /// 如果发生改变就返回true /// protected virtual bool Hover(MouseEventArgs e) { if (this.AllowMouseHover) { if (this.Initialized) { var pt = ClientToDispPoint(e.Location); var hoverList = _network.Hover(pt); if (hoverList == null || hoverList.Count < 1) { if (_lastHoverList == null || _lastHoverList.Count < 1) { return false; } } _lastHoverList = hoverList; return true; } } if (_lastHoverList == null || _lastHoverList.Count < 1) { return false; } return true; } #endregion #region 鼠标左键点击选择 /// /// 允许鼠标左键单击选择 /// [Browsable(true)] [Description("允许鼠标左键单击选择")] [DefaultValue(true)] public bool AllowMouseLeftSingleClickSelect { get => _allowMouseLeftSingleClickSelect; set => _allowMouseLeftSingleClickSelect = value; } private bool _allowMouseLeftSingleClickSelect = true; private List _lastMouseLeftClickSelectList = null;//最后一次鼠标左键单击选择列表 /// /// 当鼠标左键单击时选择 /// protected virtual bool SelectWhenMouseLeftSingleClick(MouseEventArgs e) { if (e.Button == MouseButtons.Left) { if (e.Clicks == 1) { if (this.Initialized) { var pt = ClientToDispPoint(e.Location); var selectList = _network.Select(pt); if (selectList == null || selectList.Count < 1) { if (_lastMouseLeftClickSelectList == null || _lastMouseLeftClickSelectList.Count < 1) { return false; } } _lastMouseLeftClickSelectList = selectList; return true; } } } if (_lastMouseLeftClickSelectList == null || _lastMouseLeftClickSelectList.Count < 1) { return false; } return true; } #endregion #region 鼠标滚轮滚动缩放 /// /// 当鼠标滚轮滚动时允许缩放 /// [Browsable(true)] [Description("当鼠标滚轮滚动时允许缩放")] [DefaultValue(true)] public bool AllowZoomWhenMouseWheelRoll { get => _allowZoomWhenMouseWheelRoll; set => _allowZoomWhenMouseWheelRoll = value; } private bool _allowZoomWhenMouseWheelRoll = true; /// /// 当鼠标滚轮滚动时缩放 /// protected virtual bool ZoomWhenMouseWheelRoll(MouseEventArgs e) { if (e.Delta != 0) { if (this.AllowZoomWhenMouseWheelRoll) { if (this.Initialized) { ZoomToPoint(e); return true; } } } return false; } #endregion #region 释放资源 /// /// 释放资源 /// protected virtual void DisposeResources() { if (_cache != null) { _cache.Dispose(); } } #endregion /// /// 重绘 /// protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); DrawCustomBorder(e.Graphics); DrawCache(); ApplyCache(e.Graphics); } /// /// 界面尺寸发生改变 /// /// protected override void OnResize(EventArgs eventargs) { base.OnResize(eventargs); _clientRectf = GetClientRectangleF(); ZoomAll(); CreateCache(); this.Invalidate(); } /// /// 鼠标按下 /// protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); HasMouseLeftDown(e); HasMouseRightDown(e); } /// /// 鼠标移动 /// protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); var hoverResult = Hover(e); var hasMouseLeftDownMove = MouseLeftDownMove(e); var hasMouseRightDownMove = MouseRightDownMove(e); if (hoverResult || hasMouseLeftDownMove || hasMouseRightDownMove) { this.Invalidate(); } } /// /// 鼠标弹起 /// protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); var hasMouseLeftUp = HasMouseLeftUp(e); var hasMouseRightUp = HasMouseRightUp(e); var mouseLeftSingleClickSelectResult = SelectWhenMouseLeftSingleClick(e); if (hasMouseLeftUp || hasMouseRightUp || mouseLeftSingleClickSelectResult) { this.Invalidate(); } } //鼠标滚轮滚动 protected override void OnMouseWheel(MouseEventArgs e) { base.OnMouseWheel(e); var zoomWhenMouseWheelRollResult = ZoomWhenMouseWheelRoll(e); if (zoomWhenMouseWheelRollResult) { this.Refresh(); } } /// /// 鼠标双击 /// protected override void OnMouseDoubleClick(MouseEventArgs e) { base.OnMouseDoubleClick(e); var zoomAllWhenMouseLeftDoubleClickResult = ZoomAllWhenMouseLeftDoubleClick(e); if (zoomAllWhenMouseLeftDoubleClickResult) { this.Invalidate(); } } } }