From 8f677b1741b78e4de4c95373fc02587a05d7b5ca Mon Sep 17 00:00:00 2001 From: lixiaojun <1287241240@qq.com> Date: 星期五, 16 八月 2024 17:52:08 +0800 Subject: [PATCH] 2d尝试,功能基本实现,还差绘制特定区域 --- WinFrmUI/Yw.WinFrmUI.Hydro.L2d.Core/02-panel/NetworkPanel.cs | 526 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 466 insertions(+), 60 deletions(-) diff --git a/WinFrmUI/Yw.WinFrmUI.Hydro.L2d.Core/02-panel/NetworkPanel.cs b/WinFrmUI/Yw.WinFrmUI.Hydro.L2d.Core/02-panel/NetworkPanel.cs index 52074f2..7f33106 100644 --- a/WinFrmUI/Yw.WinFrmUI.Hydro.L2d.Core/02-panel/NetworkPanel.cs +++ b/WinFrmUI/Yw.WinFrmUI.Hydro.L2d.Core/02-panel/NetworkPanel.cs @@ -1,4 +1,5 @@ -锘縩amespace Yw.WinFrmUI.HydroL2d +锘� +namespace Yw.WinFrmUI.HydroL2d { /// <summary> /// 绠$綉闈㈡澘 @@ -19,25 +20,29 @@ //璁剧疆鍏佽鐨勬渶灏忓昂瀵� this.MinimumSize = new Size(10, 10); - } - private Network _network = null;//绠$綉 - private Bitmap _cache = null;//缁樺埗缂撳瓨 - private float _zoomMin = 1;//鏈�灏忕缉鏀惧眰绾� - private float _zoomMax = 3200;//鏈�澶х缉鏀惧眰绾� - private float _zoom = 1;//褰撳墠缂╂斁灞傜骇 - private float _dxo = 0;//x鍋忕Щ閲� - private float _dyo = 0;//y鍋忕Щ閲� + protected Network _network = null;//绠$綉 + protected RectangleF _networkBounds;//绠$綉杈圭晫 + private Bitmap _cache = null;//缂撳瓨<渚濇嵁宸ヤ綔鍖哄煙鍒涘缓鐨勭┖鍥剧墖> + private object _cacheLocker = new();//缂撳瓨閿� + private Bitmap _disp = null;//鏄剧ず<鍦╟ache鍩虹涓婅繘琛岀粯鍒讹紝鏈�缁堢殑鏄剧ず鍥剧墖> + private object _dispLocker = new();//鏄剧ず閿� + private float _zoomMin = 0.01f;//鏈�灏忕缉鏀惧眰绾� + private float _zoomMax = 10000f;//鏈�澶х缉鏀惧眰绾� + private float _zoom = 1f;//褰撳墠缂╂斁灞傜骇 + private float _dxo = 0f;//x鍋忕Щ閲� + private float _dyo = 0f;//y鍋忕Щ閲� + private RectangleF _clientRectf;//宸ヤ綔鍖哄煙鐭╁舰 + + + #region 鍒濆鍖� /// <summary> /// 鏄惁鍒濆鍖� /// </summary> public bool Initialized => _network != null; - - - /// <summary> /// 鍒濆鍖� @@ -45,42 +50,385 @@ public virtual void Initial(Network network) { _network = network; + _networkBounds = _network.GetBounds(); + _clientRectf = GetClientRectangleF(); + CreateCache(); ZoomAll(); } - protected override void OnPaint(PaintEventArgs e) + #endregion + + #region 缂撳瓨涓庢樉绀� + + /// <summary> + /// 鍒涘缓缂撳瓨 + /// </summary> + protected virtual void CreateCache() { - base.OnPaint(e); if (!Initialized) { return; } - try + var img = new Bitmap((int)_clientRectf.Width, (int)_clientRectf.Height); + img.MakeTransparent(Color.White); + lock (_cacheLocker) { - e.Graphics.PageUnit = GraphicsUnit.Pixel; - e.Graphics.InterpolationMode = InterpolationMode.High; - e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; - e.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - e.Graphics.PageScale = _zoom; - e.Graphics.TranslateTransform(_dxo, _dyo); - e.Graphics.ScaleTransform(1, -1); + if (_cache != null) + { + _cache.Dispose(); + } + _cache = img; } - catch - { - return; - } - _network.Draw(e.Graphics); } /// <summary> - /// 鐣岄潰灏哄鍙戠敓鏀瑰彉 + /// 缁樺埗缂撳瓨 /// </summary> - /// <param name="eventargs"></param> - protected override void OnResize(EventArgs eventargs) + protected virtual void DrawCache() { - base.OnResize(eventargs); - ZoomAll(); + if (!Initialized) + { + return; + } + if (_cache == null) + { + return; + } + var disp = _cache.CloneC(); + if (disp == null) + { + return; + } + var dispRect = GetDispRectangleF(); + using (var g = Graphics.FromImage(disp)) + { + 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); + _network.Draw(g); + } + lock (_dispLocker) + { + if (_disp != null) + { + _disp.Dispose(); + } + _disp = disp; + } } + + /// <summary> + /// 搴旂敤缂撳瓨 + /// </summary> + protected virtual void ApplyCache(Graphics g) + { + if (!Initialized) + { + return; + } + lock (_dispLocker) + { + if (_disp != null) + { + g.DrawImage(_disp, _clientRectf); + } + } + + } + + #endregion + + #region 缂╂斁 + + /// <summary> + /// 缂╂斁绛夌骇 + /// </summary> + 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; + } + } + } + + /// <summary> + /// 鑷�傚簲 + /// </summary> + 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 杈规缁樺埗 + + /// <summary> + /// 杈规棰滆壊 + /// </summary> + [Browsable(true)] + [Description("鑷畾涔夎竟妗嗛鑹�")] + public Color CustomBorderColor + { + get { return _customBorderColor; } + set { _customBorderColor = value; } + } + private Color _customBorderColor = Color.Gray; + + /// <summary> + /// 杈规瀹藉害 + /// </summary> + [Browsable(true)] + [Description("鑷畾涔夎竟妗嗗搴�")] + public int CustomBorderWidth + { + get { return _customBorderWidth; } + set { _customBorderWidth = value; } + } + private int _customBorderWidth = 1; + + /// <summary> + /// 杈规鏄惁鏄剧ず + /// </summary> + [Browsable(true)] + [Description("鑷畾涔夎竟妗嗗彲瑙佹��")] + [DefaultValue(false)] + public bool CustomBorderVisible + { + get { return _customBorderVisible; } + set + { + _customBorderVisible = value; + } + } + private bool _customBorderVisible = false; + + /// <summary> + /// 缁樺埗鑷畾涔夎竟妗� + /// </summary> + 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 鑾峰彇鐭╁舰 + + /// <summary> + /// 鑾峰彇宸ヤ綔鍖哄煙 + /// </summary> + /// <returns></returns> + protected virtual RectangleF GetClientRectangleF() + { + return new RectangleF(0, 0, this.Width, this.Height); + } + + /// <summary> + /// 鑾峰彇鏄剧ず鍖哄煙 + /// </summary> + protected virtual RectangleF GetDispRectangleF() + { + if (_clientRectf.IsEmpty) + { + return default; + } + if (!Initialized) + { + return default; + } + var pt = ClientToDispPoint(_clientRectf.Location); + var width = _clientRectf.Width / _zoom; + var height = _clientRectf.Height / _zoom; + return new RectangleF(pt, new SizeF(width, height)); + } + + #endregion + + #region 榧犳爣宸﹂敭鎸変笅鎷栧姩 + + /// <summary> + /// 褰撻紶鏍囧乏閿寜涓嬫椂鍏佽鎷栧姩 + /// </summary> + [Browsable(true)] + [Description("褰撻紶鏍囧乏閿寜涓嬫椂鍏佽鎷栧姩")] + [DefaultValue(true)] + public bool AllowMoveWhenMouseLeftDown + { + get => _allowMoveWhenMouseLeftDown; + set => _allowMoveWhenMouseLeftDown = value; + } + private bool _allowMoveWhenMouseLeftDown = true; + + protected bool _hasMouseLeftDown = false;//榧犳爣宸﹂敭鏄惁鎸変笅 + protected Point _mouseLeftDownMovePoint;//榧犳爣宸﹂敭鎸変笅绉诲姩鐐� + + /// <summary> + /// 鍒ゆ柇榧犳爣宸﹂敭鏄惁鎸変笅 + /// </summary> + protected virtual bool HasMouseLeftDown(MouseEventArgs e) + { + if (e.Button == MouseButtons.Left) + { + if (Initialized) + { + if (this.AllowMoveWhenMouseLeftDown) + { + _hasMouseLeftDown = true; + _mouseLeftDownMovePoint = e.Location; + return true; + } + } + } + return true; + } + + /// <summary> + /// 榧犳爣宸﹂敭鎸変笅绉诲姩 + /// </summary> + /// <param name="e"></param> + protected virtual bool MouseLeftDownMove(MouseEventArgs e) + { + if (e.Button == MouseButtons.Left) + { + if (this.AllowMoveWhenMouseLeftDown) + { + if (_hasMouseLeftDown) + { + if (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; + } + + /// <summary> + /// 鍒ゆ柇榧犳爣宸﹂敭鏄惁寮硅捣 + /// </summary> + protected virtual bool HasMouseLeftUp(MouseEventArgs e) + { + _hasMouseLeftDown = false; + return true; + } + + #endregion + + #region 榧犳爣鍙屽嚮鎭㈠鑷�傚簲 + + /// <summary> + /// 褰撻紶鏍囧弻鍑绘椂鍏佽鑷�傚簲 + /// </summary> + [Browsable(true)] + [Description("褰撻紶鏍囧弻鍑绘椂鍏佽鑷�傚簲")] + [DefaultValue(true)] + public bool AllowZoomAllWhenMouseDoubleClick + { + get => _allowZoomAllWhenMouseDoubleClick; + set => _allowZoomAllWhenMouseDoubleClick = value; + } + private bool _allowZoomAllWhenMouseDoubleClick = true; + + /// <summary> + /// 榧犳爣鍙屽嚮鏃惰嚜閫傚簲 + /// </summary> + protected virtual bool ZoomAllWhenMouseDoubleClick(MouseEventArgs e) + { + if (e.Clicks > 1) + { + if (AllowZoomAllWhenMouseDoubleClick) + { + ZoomAll(); + return true; + } + } + return true; + } + + #endregion + + #region 閲婃斁璧勬簮 /// <summary> /// 閲婃斁璧勬簮 @@ -94,51 +442,109 @@ } + #endregion + + #region 閫夋嫨 /// <summary> - /// 鑷�傚簲 + /// 閫夋嫨锛堥�氳繃鐐归�夋嫨锛� /// </summary> - public void ZoomAll() + protected virtual List<Parter> Select(MouseEventArgs e) { - if (!Initialized) - { - return; - } - - float w = Width; - float h = Height; - var networkBounds = _network.GetBounds(); - if (networkBounds.IsEmpty) - { - return; - } - _zoom = networkBounds.Width / networkBounds.Height < w / h ? - h / networkBounds.Height : - w / networkBounds.Width; - - - _dxo = -networkBounds.X; - _dyo = networkBounds.Bottom; - - _zoom *= 0.95f; - - _dxo += w * 0.5f / _zoom - networkBounds.Width * 0.5f; - _dyo += h * 0.5f / _zoom - networkBounds.Height * 0.5f; - - Invalidate(); + var pt = ClientToDispPoint(e.Location); + var list = _network.Select(pt); + return list; } + /// <summary> + /// 鎮仠 + /// </summary> + protected virtual List<Parter> Hover(MouseEventArgs e) + { + var pt = ClientToDispPoint(e.Location); + var list = _network.Hover(pt); + return list; + } + #endregion + /// <summary> + /// 閲嶇粯 + /// </summary> + protected override void OnPaint(PaintEventArgs e) + { + base.OnPaint(e); + DrawCustomBorder(e.Graphics); + DrawCache(); + ApplyCache(e.Graphics); + } + /// <summary> + /// 鐣岄潰灏哄鍙戠敓鏀瑰彉 + /// </summary> + /// <param name="eventargs"></param> + protected override void OnResize(EventArgs eventargs) + { + base.OnResize(eventargs); + _clientRectf = GetClientRectangleF(); + ZoomAll(); + CreateCache(); + this.Invalidate(); + } + /// <summary> + /// 榧犳爣鎸変笅 + /// </summary> + protected override void OnMouseDown(MouseEventArgs e) + { + base.OnMouseDown(e); + HasMouseLeftDown(e); + } + /// <summary> + /// 榧犳爣绉诲姩 + /// </summary> + protected override void OnMouseMove(MouseEventArgs e) + { + base.OnMouseMove(e); + Hover(e); + MouseLeftDownMove(e); + this.Invalidate(); + } + /// <summary> + /// 榧犳爣寮硅捣 + /// </summary> + protected override void OnMouseUp(MouseEventArgs e) + { + base.OnMouseUp(e); + HasMouseLeftUp(e); + Select(e); + this.Invalidate(); + } + //榧犳爣婊氳疆婊氬姩 + protected override void OnMouseWheel(MouseEventArgs e) + { + base.OnMouseWheel(e); + ZoomToPoint(e); + this.Refresh(); + } + /// <summary> + /// 榧犳爣鍙屽嚮 + /// </summary> + protected override void OnMouseDoubleClick(MouseEventArgs e) + { + base.OnMouseDoubleClick(e); + if (ZoomAllWhenMouseDoubleClick(e)) + { + this.Invalidate(); + } + } } } -- Gitblit v1.9.3