public partial class RadarExt : Control { private Timer timeInterval; private Timer flickerInterval; private int angle = 0; private bool flickerStatus = false; private Color areaColor = Color.LawnGreen; /// <summary> /// 雷达区域背景颜色 /// </summary> [DefaultValue(typeof(Color), "LawnGreen")] [Description("雷达区域背景颜色")] public Color AreaColor { get { return this.areaColor; } set { if (this.areaColor == value) return; this.areaColor = value; this.Invalidate(); } } private Color scanColor = Color.Coral; /// <summary> /// 雷达扫描背景颜色 /// </summary> [DefaultValue(typeof(Color), "Coral")] [Description("雷达扫描背景颜色")] public Color ScanColor { get { return this.scanColor; } set { if (this.scanColor == value) return; this.scanColor = value; this.Invalidate(); } } private bool areaCross = true; /// <summary> /// 雷达区域是否显示十字线 /// </summary> [DefaultValue(true)] [Description("雷达区域是否显示十字线")] public bool AreaCross { get { return this.areaCross; } set { if (this.areaCross == value) return; this.areaCross = value; this.Invalidate(); } } private Color areaCrossColor = Color.YellowGreen; /// <summary> /// 雷达区域十字线颜色 /// </summary> [DefaultValue(typeof(Color), "YellowGreen")] [Description("雷达区域十字线颜色")] public Color AreaCrossColor { get { return this.areaCrossColor; } set { if (this.areaCrossColor == value) return; this.areaCrossColor = value; this.Invalidate(); } } private bool pointFlicker = true; /// <summary> /// 坐标是否闪烁 /// </summary> [DefaultValue(true)] [Description("坐标是否闪烁")] public bool PointFlicker { get { return this.pointFlicker; } set { if (this.pointFlicker == value) return; this.pointFlicker = value; this.flickerInterval.Enabled = value; this.Invalidate(); } } private Color pointColor = Color.DeepSkyBlue; /// <summary> /// 坐标颜色 /// </summary> [DefaultValue(typeof(Color), "DeepSkyBlue")] [Description("坐标颜色")] public Color PointColor { get { return this.pointColor; } set { if (this.pointColor == value) return; this.pointColor = value; this.Invalidate(); } } private int pointDiameter = 4; /// <summary> /// 坐标圆点直径 /// </summary> [DefaultValue(4)] [Description("坐标圆点直径")] public int PointDiameter { get { return this.pointDiameter; } set { if (this.pointDiameter == value) return; this.pointDiameter = value; this.Invalidate(); } } private List<XY> items; /// <summary> /// 坐标 /// </summary> [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] [Description("坐标")] public List<XY> Items { get { if (this.items == null) this.items = new List<XY>(); return this.items; } set { this.items = value; this.Invalidate(); } } private float proportion = 1; /// <summary> /// 坐标一像素表示实际长度(例如187.3表示一个像素代表实际187.3) /// </summary> [DefaultValue(1)] [Description("坐标一像素的实际比例")] public float Proportion { get { return this.proportion; } set { if (this.proportion == value) return; this.proportion = value; this.Invalidate(); } } protected override Size DefaultSize { get { return new Size(100, 100); } } public RadarExt() { SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.AllPaintingInWmPaint, true); SetStyle(ControlStyles.OptimizedDoubleBuffer, true); SetStyle(ControlStyles.ResizeRedraw, true); SetStyle(ControlStyles.SupportsTransparentBackColor, true); InitializeComponent(); this.timeInterval = new Timer(); this.timeInterval.Interval = 50; this.timeInterval.Tick += new EventHandler(this.timeInterval_Tick); this.timeInterval.Enabled = true; this.flickerInterval = new Timer(); this.flickerInterval.Interval = 500; this.flickerInterval.Tick += new EventHandler(this.flickerInterval_Tick); if (this.pointFlicker) { this.flickerInterval.Enabled = true; } } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); Graphics g = e.Graphics; g.SmoothingMode = SmoothingMode.AntiAlias; Rectangle rect = e.ClipRectangle; GraphicsPath graphicsPath = new GraphicsPath(); graphicsPath.AddEllipse(rect); PathGradientBrush area_pgb = new PathGradientBrush(graphicsPath); area_pgb.CenterColor = this.areaColor; area_pgb.CenterPoint = new PointF(rect.Width / 2, rect.Height / 2); area_pgb.SurroundColors = new Color[] { Color.Transparent }; g.FillEllipse(area_pgb, rect); PathGradientBrush scan_pgb = new PathGradientBrush(graphicsPath); scan_pgb.CenterColor = this.scanColor; scan_pgb.CenterPoint = new PointF(rect.Width / 2, rect.Height / 2); scan_pgb.SurroundColors = new Color[] { Color.Transparent }; g.FillPie(scan_pgb, rect, this.angle, 90); area_pgb.Dispose(); scan_pgb.Dispose(); if (this.areaCross) { PathGradientBrush cross_pgb = new PathGradientBrush(graphicsPath); cross_pgb.CenterColor = this.areaCrossColor; cross_pgb.CenterPoint = new PointF(rect.Width / 2, rect.Height / 2); cross_pgb.SurroundColors = new Color[] { Color.Transparent }; Pen cross_pen = new Pen(cross_pgb); g.DrawLine(cross_pen, 0, rect.Height / 2, rect.Width, rect.Height / 2); g.DrawLine(cross_pen, rect.Width / 2, 0, rect.Width / 2, rect.Height); cross_pgb.Dispose(); cross_pen.Dispose(); } if (!this.pointFlicker || (this.pointFlicker && this.flickerStatus)) { Point point = new Point(rect.Width / 2, rect.Height / 2); for (int i = 0; i < Items.Count; i++) { int x = point.X + (int)(Items[i].X / this.proportion) - this.pointDiameter / 2; int y = point.Y + (int)(Items[i].Y / this.proportion) - this.pointDiameter / 2; if (graphicsPath.IsVisible(x, y)) { SolidBrush point_sb = new SolidBrush(this.pointColor); g.FillEllipse(point_sb, new Rectangle(x, y, this.pointDiameter, this.pointDiameter)); point_sb.Dispose(); } } } g.SmoothingMode = SmoothingMode.Default; graphicsPath.Dispose(); } protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) { base.SetBoundsCore(x, y, width, width, specified); } private void timeInterval_Tick(object sender, EventArgs e) { this.angle += 10; if (this.angle > 360) this.angle = this.angle - 360; this.Invalidate(); } private void flickerInterval_Tick(object sender, EventArgs e) { this.flickerStatus = !this.flickerStatus; this.Invalidate(); } protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); if (this.timeInterval != null) { this.timeInterval.Dispose(); } if (this.flickerInterval != null) { this.flickerInterval.Dispose(); } } base.Dispose(disposing); } /// <summary> /// 实际坐标 /// </summary> public class XY { /// <summary> /// X实际坐标 /// </summary> [DefaultValue(0)] public float X { get; set; } /// <summary> /// Y实际坐标 /// </summary> [DefaultValue(0)] public float Y { get; set; } } }