using System;
|
using System.Collections.Generic;
|
using System.Drawing;
|
using System.Drawing.Drawing2D;
|
using System.Linq;
|
using System.Windows.Forms;
|
|
namespace CloudWaterNetwork
|
{
|
partial class MapControl : Control
|
{
|
private Point backgroundImageOffset = Point.Empty; // 背景图偏移量
|
private Image backgroundImage; // 背景图片
|
private RectangleF chartArea; // 直角坐标系范围
|
private PointF origin; // 坐标轴原点
|
private float zoomLevel = 1f; // 缩放级别
|
|
private bool isPanning = false; // 是否正在平移
|
private Point lastMousePosition = Point.Empty; // 上一次鼠标位置
|
private bool isSelecting = false; // 是否正在框选矩形
|
private RectangleF selectionRect; // 框选矩形
|
|
|
public MapControl()
|
{
|
this.DoubleBuffered = true;
|
}
|
|
public Image BackgroundImage
|
{
|
get { return this.backgroundImage; }
|
set
|
{
|
this.backgroundImage = value;
|
this.Invalidate();
|
}
|
}
|
|
protected override void OnMouseDown(MouseEventArgs e)
|
{
|
base.OnMouseDown(e);
|
|
if (e.Button == MouseButtons.Middle)
|
{
|
// 启动平移模式
|
this.isPanning = true;
|
this.lastMousePosition = e.Location;
|
}
|
else if (e.Button == MouseButtons.Left)
|
{
|
// 启动框选矩形模式
|
this.isSelecting = true;
|
this.selectionRect = new RectangleF(e.Location, SizeF.Empty);
|
}
|
}
|
|
protected override void OnMouseMove(MouseEventArgs e)
|
{
|
base.OnMouseMove(e);
|
|
if (this.isPanning)
|
{
|
// 平移坐标系范围和背景图片
|
int dx = e.X - this.lastMousePosition.X;
|
int dy = e.Y - this.lastMousePosition.Y;
|
this.backgroundImageOffset.Offset(dx, dy);
|
this.chartArea.Offset(dx / this.zoomLevel, -dy / this.zoomLevel);
|
this.origin.X += dx;
|
this.origin.Y += dy;
|
//Offset(dx, dy);
|
this.lastMousePosition = e.Location;
|
this.Invalidate();
|
}
|
else if (this.isSelecting)
|
{
|
// 更新框选矩形范围
|
this.selectionRect.Width = e.X - this.selectionRect.Left;
|
this.selectionRect.Height = e.Y - this.selectionRect.Top;
|
this.Invalidate();
|
}
|
}
|
|
protected override void OnMouseUp(MouseEventArgs e)
|
{
|
base.OnMouseUp(e);
|
|
if (this.isPanning)
|
{
|
// 停止平移模式
|
this.isPanning = false;
|
}
|
else if (this.isSelecting)
|
{
|
// 停止框选矩形模式,并重新计算坐标系范围和原点位置
|
this.isSelecting = false;
|
|
float x1 = (this.selectionRect.Left - this.origin.X) * (this.chartArea.Width / this.ClientSize.Width) + this.chartArea.Left;
|
float y1 = (this.ClientSize.Height - this.selectionRect.Bottom + this.origin.Y) * (this.chartArea.Height / this.ClientSize.Height) + this.chartArea.Top;
|
float x2 = (this.selectionRect.Right - this.origin.X) * (this.chartArea.Width / this.ClientSize.Width) + this.chartArea.Left;
|
float y2 = (this.ClientSize.Height - this.selectionRect.Top + this.origin.Y) * (this.chartArea.Height / this.ClientSize.Height) + this.chartArea.Top;
|
|
this.chartArea = new RectangleF(x1, y1, x2 - x1, y2 - y1);
|
this.origin = new PointF(this.chartArea.Left, this.chartArea.Bottom);
|
|
this.Invalidate();
|
}
|
}
|
|
protected override void OnMouseWheel(MouseEventArgs e)
|
{
|
base.OnMouseWheel(e);
|
|
// 缩放坐标系范围和背景图片
|
float factor = e.Delta > 0 ? 1.1f : 0.9f;
|
float oldZoomLevel = this.zoomLevel;
|
this.zoomLevel *= factor;
|
if (this.zoomLevel < 0.1f)
|
{
|
this.zoomLevel = 0.1f;
|
}
|
if (this.zoomLevel > 10f)
|
{
|
this.zoomLevel = 10f;
|
}
|
float dx = (this.chartArea.Width / oldZoomLevel - this.chartArea.Width / this.zoomLevel) / 2;
|
float dy = (this.chartArea.Height / oldZoomLevel - this.chartArea.Height / this.zoomLevel) / 2;
|
this.backgroundImageOffset.Offset((int)(e.Location.X * dx), (int)(e.Location.Y * dy));
|
this.chartArea.Inflate(dx, dy);
|
this.origin = new PointF(this.chartArea.Left, this.chartArea.Bottom);
|
|
this.Invalidate();
|
}
|
|
protected override void OnPaint(PaintEventArgs e)
|
{
|
base.OnPaint(e);
|
|
// 绘制背景图片
|
if (this.backgroundImage != null)
|
{
|
e.Graphics.DrawImage(this.backgroundImage, this.backgroundImageOffset);
|
}
|
|
// 绘制直角坐标系和矩形
|
using (Pen axisPen = new Pen(Color.Black, 2))
|
{
|
e.Graphics.DrawLine(axisPen, this.origin.X, this.origin.Y, this.origin.X + this.chartArea.Width / this.zoomLevel, this.origin.Y); // X轴
|
e.Graphics.DrawLine(axisPen, this.origin.X, this.origin.Y, this.origin.X, this.origin.Y - this.chartArea.Height / this.zoomLevel); // Y轴
|
|
if (this.isSelecting)
|
{
|
// 绘制框选矩形
|
using (Pen selectionPen = new Pen(Color.Red, 2))
|
{
|
selectionPen.DashStyle = DashStyle.Dot;
|
e.Graphics.DrawRectangle(selectionPen, Rectangle.Round(this.selectionRect));
|
}
|
}
|
}
|
}
|
|
protected override void OnResize(EventArgs e)
|
{
|
base.OnResize(e);
|
|
// 初始化坐标系范围和原点位置
|
float widthRatio = (float)this.ClientSize.Width / this.chartArea.Width;
|
float heightRatio = (float)this.ClientSize.Height / this.chartArea.Height;
|
float zoomRatio = Math.Min(widthRatio, heightRatio);
|
this.chartArea = new RectangleF(0, 0, this.ClientSize.Width / zoomRatio, this.ClientSize.Height / zoomRatio);
|
this.origin = new PointF(this.chartArea.Left, this.chartArea.Bottom);
|
|
this.Invalidate();
|
}
|
}
|
}
|