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();
}
}
}
}