winform中使用ZedGraphControl控件做图

winform中使用ZedGraphControl控件做图。

一些方法的总结

 public class ChartEx : ZedGraph.ZedGraphControl
    {

        #region init
        private readonly Color[] colorPool = new Color[8];
        public int colorPoolIndex { get; set; } = 0;

        public ChartEx() : base()
        {
            InitGui();
            InitColorPool();
        }

        private void InitGui()
        {
            this.SuspendLayout();

            this.Name = "ChartEx";
            this.Dock = DockStyle.Fill;

            this.IsZoomOnMouseCenter = false;

            this.IsEnableHZoom = true;
            this.IsEnableVZoom = true;

            this.IsSynchronizeXAxes = true;
            this.IsSynchronizeYAxes = false;
            this.IsShowPointValues = true;

            this.MasterPane.Border.IsVisible = false;
            this.MasterPane.InnerPaneGap = 1;

            this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.chartEx_MouseClick);
            this.PointValueEvent += new ZedGraphControl.PointValueHandler(this.chartEx_PointValueEvent);
            this.ZoomEvent += new ZedGraph.ZedGraphControl.ZoomEventHandler(this.chartEx_ZoomEvent);
            //this.MouseDownEvent += new ZedMouseEventHandler(this.chartEx_MouseDownEvent);

            this.ContextMenuBuilder += new ZedGraphControl.ContextMenuBuilderEventHandler(this.chartEx_ContextMenuBuilder);

            this.ResumeLayout(false);
        }
        #endregion


        private void InitColorPool()
        {
            colorPool[0] = ColorPool.Pool[0];
            colorPool[1] = ColorPool.Pool[1];
            colorPool[2] = ColorPool.Pool[2];
            colorPool[3] = ColorPool.Pool[3];
            colorPool[4] = ColorPool.Pool[4];
            colorPool[5] = ColorPool.Pool[5];
            colorPool[6] = ColorPool.Pool[6];
            colorPool[7] = ColorPool.Pool[7];
        }

        public Color GetNextColor()
        {
            var color = colorPool[0];
            if (colorPoolIndex >= colorPool.Length)
            {
                colorPoolIndex = 0;
            }
            color = colorPool[colorPoolIndex];
            colorPoolIndex++;
            return color;
        }

        #region public function
        public GraphPane FormatGraphPane(GraphPane gp)
        {
            gp.Border.IsVisible = false;
            gp.Title.IsVisible = false;
            gp.IsFontsScaled = false;

            gp.Margin.All = 1;

            gp.Legend.IsVisible = true;
            gp.Legend.FontSpec.Size = 11;
            gp.Legend.FontSpec.FontColor = Color.Black;
            gp.Legend.Fill = new Fill(Color.FromArgb(255, 255, 255, 255), Color.FromArgb(255, 255, 255, 255));
            gp.Legend.Border.IsVisible = false;

            gp.Chart.Border.Color = Color.LightGray;
            gp.Fill = new Fill(Color.White, Color.White, 0F);
            gp.Chart.Fill = new Fill(Color.White, Color.White, 0);

            if (gp.XAxis != null) FormatXAxis(gp.XAxis);
            if (gp.YAxis != null) FormatYAxis(gp.YAxis);

            return gp;
        }

        public XAxis FormatXAxis(XAxis xAxis)
        {
            xAxis.Title.IsVisible = false;
            xAxis.Title.FontSpec.Size = 11;
            xAxis.Scale.FontSpec.Size = 11;
            xAxis.MajorTic.Color = Color.Gray;
            xAxis.MinorTic.Color = Color.LightGray;
            xAxis.Scale.FontSpec.FontColor = Color.Gray;
            xAxis.Title.FontSpec.FontColor = Color.Gray;
            return xAxis;
        }

        public YAxis FormatYAxis(YAxis yAxis)
        {
            yAxis.Title.IsVisible = false;
            yAxis.Title.FontSpec.Size = 11;
            yAxis.Scale.FontSpec.Size = 11;
            yAxis.Color = Color.LightGray;
            yAxis.MajorTic.Color = Color.Gray;
            yAxis.MinorTic.Color = Color.LightGray;
            yAxis.Scale.FontSpec.FontColor = Color.Gray;
            yAxis.Title.FontSpec.FontColor = Color.Gray;
            return yAxis;
        }


        public LineObj DrawLineX(GraphPane gp, double x)
        {
            return DrawLineX(gp, x, Color.Red);
        }

        public LineObj DrawLineX(GraphPane gp, double x, Color color)
        {
            this.AxisChange();
            LineObj obj = new LineObj(color, x, gp.YAxis.Scale.Min, x, gp.YAxis.Scale.Max);
            obj.Tag = "LineX";
            obj.Line.Style = DashStyle.Dash;
            obj.ZOrder = ZOrder.E_BehindCurves;
            obj.Line.Width = 1;
            gp.GraphObjList.Add(obj);
            return obj;
        }

        public LineObj DrawLineY(GraphPane gp, double y)
        {
            return DrawLineY(gp, y, Color.Red);
        }

        public LineObj DrawLineY(GraphPane gp, double y, Color color)
        {
            this.AxisChange();
            LineObj obj = new LineObj(color, gp.XAxis.Scale.Min, y, gp.XAxis.Scale.Max, y);
            obj.Tag = "LineY";
            obj.Line.Style = DashStyle.Dash;
            obj.ZOrder = ZOrder.E_BehindCurves;
            obj.Line.Width = 1;
            gp.GraphObjList.Add(obj);
            return obj;
        }

        public BoxObj DrawRangeX(GraphPane gp, double x1, double x2)
        {
            return DrawRangeX(gp, x1, x2, Color.Empty, Color.FromArgb(50, Color.LightGreen));
        }

        public BoxObj DrawRangeX(GraphPane gp, double x1, double x2, Color borderColor, Color fillColor)
        {
            this.AxisChange();
            BoxObj obj = new BoxObj(x1, gp.YAxis.Scale.Max, x2 - x1, gp.YAxis.Scale.Max - gp.YAxis.Scale.Min, borderColor, fillColor);
            obj.Tag = "RangeX";
            obj.ZOrder = ZOrder.F_BehindGrid;

            //obj.IsClippedToChartRect = true;
            //obj.Location.CoordinateFrame = CoordType.AxisXYScale;
            gp.GraphObjList.Add(obj);
            return obj;
        }
        public BoxObj DrawRangeXWithText(GraphPane gp, double x1, double x2)
        {
            return DrawRangeXWithText(gp, x1, x2, Color.Empty, Color.FromArgb(50, Color.LightGreen));
        }

        //2. 多个Range范围标注文字拥挤问题:过载实现一个y轴可以偏移文字标注方法。 内部嵌套的range,y轴向下偏移一个字符的高度。 
        //ccc-285
        public List<TextObj> DrawRangeXWithText(GraphPane gp, double x1, double x2, Color borderColor, Color fillColor, int fontIndex)
        {
            var fonts = new List<TextObj>(); ;
            this.AxisChange();
            BoxObj obj = new BoxObj(x1 < x2 ? x1 : x2, gp.YAxis.Scale.Max, Math.Abs(x2 - x1), gp.YAxis.Scale.Max - gp.YAxis.Scale.Min, borderColor, fillColor);
            obj.Tag = "RangeX";
            obj.ZOrder = ZOrder.F_BehindGrid;

            //obj.IsClippedToChartRect = true;
            //obj.Location.CoordinateFrame = CoordType.AxisXYScale;
            gp.GraphObjList.Add(obj);

            if (x1 > x2)
            {
                double temp = x1;
                x1 = x2;
                x2 = temp;
            }


            fonts.Add(DrawTextX(gp, x1, $"{x1}>", Color.Black, fontIndex, AlignH.Right));
            fonts.Add(DrawTextX(gp, x2, $"<{x2}", Color.Black, fontIndex, AlignH.Left));
            return fonts;
        }


        public BoxObj DrawRangeXWithText(GraphPane gp, double x1, double x2, Color borderColor, Color fillColor)
        {
            this.AxisChange();
            BoxObj obj = new BoxObj(x1 < x2 ? x1 : x2, gp.YAxis.Scale.Max, Math.Abs(x2 - x1), gp.YAxis.Scale.Max - gp.YAxis.Scale.Min, borderColor, fillColor);
            obj.Tag = "RangeX";
            obj.ZOrder = ZOrder.F_BehindGrid;

            //obj.IsClippedToChartRect = true;
            //obj.Location.CoordinateFrame = CoordType.AxisXYScale;
            gp.GraphObjList.Add(obj);

            if (x1 > x2)
            {
                double temp = x1;
                x1 = x2;
                x2 = temp;
            }
            DrawTextX(gp, x1, $"{x1}>", Color.Black, AlignH.Right);
            DrawTextX(gp, x2, $"<{x2}", Color.Black, AlignH.Left);
            return obj;
        }

        public BoxObj DrawRangeY(GraphPane gp, double y1, double y2)
        {
            return DrawRangeY(gp, y1, y2, Color.Empty, Color.FromArgb(50, Color.LightGreen));
        }

        public BoxObj DrawRangeY(GraphPane gp, double y1, double y2, Color borderColor, Color fillColor)
        {
            this.AxisChange();
            BoxObj obj = new BoxObj(gp.XAxis.Scale.Min, y2, gp.XAxis.Scale.Max - gp.XAxis.Scale.Min, y2 - y1, borderColor, fillColor);
            obj.Tag = "RangeY";
            obj.ZOrder = ZOrder.F_BehindGrid;
            //box.IsClippedToChartRect = true;
            //box.Location.CoordinateFrame = CoordType.AxisXYScale;
            gp.GraphObjList.Add(obj);
            return obj;
        }

        public TextObj DrawTextX(GraphPane gp, double x, string text, Color color, AlignH alignH = AlignH.Left)
        {
            this.AxisChange();
            TextObj obj = new TextObj(text, x, gp.YAxis.Scale.Max, CoordType.AxisXYScale, alignH, AlignV.Top);
            obj.Tag = "TextX";
            obj.FontSpec.Border.IsVisible = false;
            obj.FontSpec.Fill.Color = Color.FromArgb(0, 0, 0, 0);
            obj.FontSpec.Size = 12;
            obj.FontSpec.FontColor = color;
            obj.ZOrder = ZOrder.E_BehindCurves;
            gp.GraphObjList.Add(obj);
            return obj;
        }
        public TextObj DrawTextX(GraphPane gp, double x, string text, Color color, int ordinal, AlignH alignH = AlignH.Left)
        {
            this.AxisChange();
            TextObj obj = new TextObj(text, x, gp.YAxis.Scale.Max, CoordType.AxisXYScale, alignH, AlignV.Top);
            obj.Tag = "TextX";
            obj.FontSpec.Border.IsVisible = false;
            obj.FontSpec.Fill.Color = Color.FromArgb(0, 0, 0, 0);
            obj.FontSpec.Size = 12;
            obj.FontSpec.FontColor = color;
            obj.ZOrder = ZOrder.E_BehindCurves;
            gp.GraphObjList.Add(obj);
            //obj.Location.Y = obj.Location.Y - ((double)ordinal) * 12;
            return obj;
        }

        public TextObj DrawTextY(GraphPane gp, double y, string text, Color color, AlignV alignV = AlignV.Top)
        {
            this.AxisChange();
            TextObj obj = new TextObj(text, gp.XAxis.Scale.Max, y, CoordType.AxisXYScale, AlignH.Right, alignV);
            obj.Tag = "TextY";
            obj.FontSpec.Border.IsVisible = false;
            obj.FontSpec.Fill.Color = Color.FromArgb(0, 0, 0, 0);
            obj.FontSpec.Size = 12;
            obj.FontSpec.FontColor = color;
            obj.ZOrder = ZOrder.E_BehindCurves;
            gp.GraphObjList.Add(obj);
            return obj;
        }
        #endregion

        #region private function

        private void chartEx_ContextMenuBuilder(ZedGraphControl control, ContextMenuStrip menuStrip, Point mousePt, ZedGraphControl.ContextMenuObjectState objState)
        {

            {//remove default menu item
                foreach (ToolStripMenuItem item in menuStrip.Items)
                {
                    if ((string)item.Tag == "page_setup") item.Visible = false;
                    if ((string)item.Tag == "print") item.Visible = false;
                    //if ((string) item.Tag == "set_default") item.Visible = false;
                    if ((string)item.Tag == "undo_all") item.Visible = false;
                    if ((string)item.Tag == "unzoom") item.Visible = false;
                }
            }

            {//add new menu item
                var sep = new ToolStripSeparator();
                menuStrip.Items.Add(sep);

                var item = new ToolStripMenuItem();
                item.Name = "menuZoomXY";
                item.Tag = "menuZoomXY";
                item.Text = "Zoom X Only";
                item.Click += new System.EventHandler(menuZoomXY_event);
                item.Checked = !this.IsEnableVZoom;
                menuStrip.Items.Add(item);
            }
        }

        protected void menuZoomXY_event(object sender, System.EventArgs e)
        {
            Logger.Debug($"menuZoomXY_event object={sender}, System.EventArgs={e}");

            this.IsEnableHZoom = true;
            this.IsEnableVZoom = !this.IsEnableVZoom;
        }

        private bool chartEx_MouseDownEvent(ZedGraphControl sender, MouseEventArgs e)
        {
            //TODO
            Logger.Debug($"chartEx_MouseDownEvent ZedGraphControl={sender}, MouseEventArgs={e}");

            foreach (GraphPane gp in sender.MasterPane.PaneList)
            {
                object clickedObject;
                var index = int.MinValue;
                var g = this.CreateGraphics();

                var isObjectFound = gp.FindNearestObject(e.Location, g, out clickedObject, out index);

                if (!isObjectFound) continue;
                if (!(clickedObject is Legend)) continue;
                if (gp.Legend == null || index < 0) continue;

                gp.CurveList.Move(index, -index);

                /*
                var nearestCurve = (LineItem)gp.CurveList[index];
                nearestCurve.IsVisible = !nearestCurve.IsVisible;
                */
            }

            return true;
        }

        private string chartEx_PointValueEvent(ZedGraphControl sender, GraphPane pane, CurveItem curve, int iPt)
        {
            var curveName = curve.Label.Text.ToString();
            var pt = curve[iPt];
            return String.Format("{0}\r\nY: {1}  [{2}]\r\nX: {3}", curveName, pt.Y, "0x" + ((long)pt.Y).ToString("X"), pt.X);
        }

        private void chartEx_ZoomEvent(ZedGraphControl sender, ZoomState oldState, ZoomState newState)
        {
            this.RefreshDraw();
        }

        private readonly Dictionary<GraphPane, LineObj> clickMarkerLineDict = new Dictionary<GraphPane, LineObj>();
        private void chartEx_MouseClick(object sender, MouseEventArgs e)
        {
            double x, y;
            try
            {
                this.GraphPane.ReverseTransform(e.Location, out x, out y);  // get X & Y CO-Ordinates by current mouse location
            }
            catch (NullReferenceException nex)
            {
                nex.ToString();
                return;
            }

            foreach (GraphPane gp in this.MasterPane.PaneList)
            {
                {   // draw dash line
                    LineObj lineX = null;
                    var isOk = clickMarkerLineDict.TryGetValue(gp, out lineX);
                    if (isOk) gp.GraphObjList.Remove(lineX); // Clear the previous values if any

                    lineX = new LineObj(Color.DarkGray, x, gp.YAxis.Scale.Min, x, gp.YAxis.Scale.Max);
                    lineX.Tag = "LineX";
                    lineX.Line.Style = DashStyle.Dash;
                    lineX.ZOrder = ZOrder.E_BehindCurves;
                    gp.GraphObjList.Add(lineX);

                    if (clickMarkerLineDict.ContainsKey(gp)) clickMarkerLineDict.Remove(gp);
                    clickMarkerLineDict.Add(gp, lineX);

                    this.Refresh();
                }
                {   // show curve on top
                    object clickedObject;
                    var index = int.MinValue;
                    var g = this.CreateGraphics();

                    var isObjectFound = gp.FindNearestObject(e.Location, g, out clickedObject, out index);

                    if (!isObjectFound) continue;
                    if (!(clickedObject is Legend)) continue;
                    if (gp.Legend == null || index < 0) continue;

                    gp.CurveList.Move(index, -index);
                }

            }

        }

        // an example for reformat y axis label
        // if (isHex) yAxis.ScaleFormatEvent += new YAxis.ScaleFormatHandler(this.chartX_ScaleFormatHandler);
        public string chartEx_ScaleFormatHandler(GraphPane pane, Axis axis, double val, int index)
        {
            var v = (long)val;
            return "0x" + v.ToString("X");
        }

        private void RefreshDraw()
        {
            foreach (var gp in this.MasterPane.PaneList)
            {
                foreach (var gObj in gp.GraphObjList)
                {
                    if (gObj is LineObj)
                    {
                        var line = (LineObj)gObj;
                        var tag = (string)line.Tag;
                        if ("LineX".Equals(tag))
                        {
                            line.Location.Y = gp.YAxis.Scale.Min;
                            line.Location.Height = gp.YAxis.Scale.Max - gp.YAxis.Scale.Min;
                        }
                        else if ("LineY".Equals(tag))
                        {
                            line.Location.X = gp.XAxis.Scale.Min;
                            line.Location.Width = gp.XAxis.Scale.Max - gp.XAxis.Scale.Min;
                        }
                    }
                    else if (gObj is BoxObj)
                    {
                        var box = (BoxObj)gObj;
                        var tag = (string)box.Tag;
                        if ("RangeX".Equals(tag))
                        {
                            box.Location.Y = gp.YAxis.Scale.Max;
                            box.Location.Height = gp.YAxis.Scale.Max - gp.YAxis.Scale.Min;
                        }
                        else if ("RangeY".Equals(tag))
                        {
                            box.Location.X = gp.XAxis.Scale.Min;
                            box.Location.Width = gp.XAxis.Scale.Max - gp.XAxis.Scale.Min;
                        }
                    }
                    else if (gObj is TextObj)
                    {
                        var text = (TextObj)gObj;
                        var tag = (string)text.Tag;
                        if ("TextX".Equals(tag))
                        {
                            text.Location.Y = gp.YAxis.Scale.Max;
                        }
                        else if ("TextY".Equals(tag))
                        {
                            text.Location.X = gp.XAxis.Scale.Max;
                        }
                    }
                }
            }

        }
        #endregion

        public static void ShowCase(DataRow[] rows, params string[] signals)
        {
            //1. draw line 1
            var chart = new ChartEx();
            var gp = chart.GraphPane;
            gp = chart.FormatGraphPane(gp);

            List<PointPairList> ppls = new List<PointPairList>();
            signals.ToList().ForEach(s =>
            {
                var ppl = new PointPairList();
                for (int i = 0; i < rows.Length; i++)
                {
                    var row = rows[i];
                    var time = (double)row["TIME"];
                    var val = (double)row[s];
                    ppl.Add(time, val);
                }
                ppls.Add(ppl);
                var line = gp.AddCurve(s, ppl, chart.GetNextColor(), SymbolType.None);
            });
            chart.AxisChange();
            chart.Refresh();

            using (var g = chart.CreateGraphics())
            {
                //chart.MasterPane.SetLayout(g, PaneLayout.SquareRowPreferred);
                chart.MasterPane.SetLayout(g, PaneLayout.SingleColumn);
            }



            var frm = new Form();
            frm.StartPosition = FormStartPosition.CenterScreen;
            frm.Controls.Add(chart);
            frm.ShowDialog();
        }
        #region showcase
        public static ChartEx ShowCase(bool inForm = true)
        {
            var ppl = new PointPairList();
            ppl.Add(1, 7);
            ppl.Add(2, 3);
            ppl.Add(3, 1);
            ppl.Add(4, 2.5);


            var ppl1 = new PointPairList();
            ppl1.Add(1, 1);
            ppl1.Add(2, 3);
            ppl1.Add(3, 6);
            ppl1.Add(4, 3);


            var ppl2 = new PointPairList();
            ppl2.Add(1, 8);
            ppl2.Add(2, 2.4);
            ppl2.Add(3, 4);
            ppl2.Add(4, 6);

            //1. draw line 1
            var chart = new ChartEx();
            var gp = chart.GraphPane;
            gp = chart.FormatGraphPane(gp);

            //gp.XAxis.Title.Text = "Timestamp (Seconds)";
            gp.YAxis.Title.Text = "lalala";

            //LineItem line = gp.AddCurve("test", ppl, Color.Blue, SymbolType.None);

            var i = gp.AddYAxis("test");
            //gp.YAxisList[i].Color = Color.Orange;
            //gp.YAxisList[i].Scale.IsVisible = false;
            //gp.YAxisList[i].MajorTic.IsAllTics = false;
            //gp.YAxisList[i].MinorTic.IsAllTics = false;

            {
                var line = gp.AddCurve("test1", ppl2, Color.Yellow, SymbolType.Default);
                line.Line.IsVisible = false;
                line.YAxisIndex = i;
            }
            {
                var line = gp.AddCurve("test1", ppl, Color.Blue, SymbolType.None);
                line.YAxisIndex = i;
            }
            var gp2 = new GraphPane();
            gp2 = chart.FormatGraphPane(gp2);
            gp2.Margin.Left = 93;
            gp2.XAxis.Title.Text = "Timestamp (Seconds)";

            chart.MasterPane.Add(gp2);
            {
                var line = gp2.AddCurve("test2", ppl1, Color.Red, SymbolType.Circle);
                line.Line.IsSmooth = true;
                //line.YAxisIndex = i;
            }

            {
                chart.DrawLineX(gp, 3.5, Color.Red);
                chart.DrawTextX(gp, 3.5, "Left", Color.Red);
                chart.DrawTextX(gp, 3.5, "Right", Color.Red, AlignH.Right);
            }
            {
                chart.DrawLineY(gp2, 3, Color.Red);
                chart.DrawTextY(gp2, 3, "top:3", Color.Red);
                chart.DrawTextY(gp2, 3, "Bottom:3", Color.Red, AlignV.Bottom);
            }
            {
                var box = chart.DrawRangeX(gp, 2, 3, Color.Empty, Color.FromArgb(150, Color.LightGreen));
                chart.DrawRangeX(gp2, 2, 3, Color.Empty, Color.FromArgb(150, Color.LightGreen));
                //BoxObj box = chart.drawRangeY(gp, 2, 3, Color.Empty, Color.FromArgb(150, Color.LightGreen));
            }


            chart.Width = 400;
            chart.Height = 300;
            //chart.AxisChange();
            chart.Refresh();

            using (var g = chart.CreateGraphics())
            {
                //chart.MasterPane.SetLayout(g, PaneLayout.SquareRowPreferred);
                chart.MasterPane.SetLayout(g, PaneLayout.SingleColumn);
            }

            //TextObj to = new TextObj("ZoomFlag", 3, 1);
            //to.FontSpec.Border.IsVisible = false;
            //to.FontSpec.Fill.Color = Color.FromArgb(0, 0, 0, 0);
            //to.FontSpec.Size = 12;
            //to.FontSpec.FontColor = Color.Blue;
            //to.ZOrder = ZOrder.E_BehindCurves;
            //gp.GraphObjList.Add(to);
            //var pf = to.Location.Transform(gp);

            var loc3 = new Location(3, 1, CoordType.AxisXYScale);
            var pf2 = loc3.Transform(gp);
            //gp2.GraphObjList.Add(to);
            //chart.Refresh();
            //gp2.XAxis.Scale.Min = 4;
            //gp2.XAxis.Scale.Max = 6;
            //var x = gp.XAxis.Scale.Max;
            //var y = gp.XAxis.Scale.Min;
            //var x1 = gp2.XAxis.Scale.Max;
            //var y1 = gp2.XAxis.Scale.Min;
            //chart.ZoomPane(gp, 5, pf2, false, true);//every +n, xaxis portion add by n*max, set false for zoom center, shrink, zoom out fraction
            //chart.AxisChange();
            chart.Refresh();

            chart.Refresh();

            var x = gp.XAxis.Scale.Max;
            var y = gp.XAxis.Scale.Min;
            var x1 = gp2.XAxis.Scale.Max;
            var y1 = gp2.XAxis.Scale.Min;
            chart.IsEnableHZoom = true;
            chart.IsEnableVZoom = false;
            double axisStart = 0;
            double axisEnd = 20;
            double fraction = (axisEnd - axisStart) / x - y;
            chart.ZoomPane(chart.GraphPane, fraction, new PointF(3, 1), false);
            gp.XAxis.Scale.Min = axisStart;
            gp.XAxis.Scale.Max = axisEnd;
            //chart.GraphPane.XAxis.Scale.Min = 0;
            //chart.GraphPane.XAxis.Scale.Max = 100;
            //chart.AxisChange();
            chart.Refresh();

            if (inForm)
            {
                var frm = new Form() { Width = 800, Height = 600 };
                frm.StartPosition = FormStartPosition.CenterScreen;
                frm.Controls.Add(chart);
                frm.ShowDialog();
            }



            return chart;
        }
        #endregion
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值