private static void ChartContext_Opening(object sender, CancelEventArgs e) { ContextMenuStrip menuStrip = (ContextMenuStrip)sender; Chart senderChart = (Chart)menuStrip.SourceControl; ChartData ptrData = ChartTool[senderChart]; //Check Zoomed state if (senderChart.ChartAreas[0].AxisX.ScaleView.IsZoomed || senderChart.ChartAreas[0].AxisY.ScaleView.IsZoomed || senderChart.ChartAreas[0].AxisY2.ScaleView.IsZoomed) { ptrData.ChartToolZoomOut.Visible = true; ptrData.ChartToolZoomOutSeparator.Visible = true; } else { ptrData.ChartToolZoomOut.Visible = false; ptrData.ChartToolZoomOutSeparator.Visible = false; } //Get Chart Control State if (!ChartTool.ContainsKey(senderChart)) { //Initialize Chart Tool SetChartControlState(senderChart, MSChartExtensionToolState.Select); } //Update menu based on current state. ptrData.ChartToolSelect.Checked = false; ptrData.ChartToolZoom.Checked = false; ptrData.ChartToolPan.Checked = false; switch (ChartTool[senderChart].ToolState) { case MSChartExtensionToolState.Select: ptrData.ChartToolSelect.Checked = true; break; case MSChartExtensionToolState.Zoom: ptrData.ChartToolZoom.Checked = true; break; case MSChartExtensionToolState.Pan: ptrData.ChartToolPan.Checked = true; break; } //Update series for (int x = 0; x < menuStrip.Items.Count; x++) { if (menuStrip.Items[x].Tag != null) { if (menuStrip.Items[x].Tag.ToString() == "Series") { menuStrip.Items.RemoveAt(x); x--; } } } SeriesCollection chartSeries = ((Chart)menuStrip.SourceControl).Series; foreach (Series ptrSeries in chartSeries) { ToolStripItem ptrItem = menuStrip.Items.Add(ptrSeries.Name); ToolStripMenuItem ptrMenuItem = (ToolStripMenuItem)ptrItem; ptrMenuItem.Checked = ptrSeries.Enabled; ptrItem.Tag = "Series"; } }
/// <summary> /// Enable Zoom and Pan Controls. /// </summary> /// <param name="sender">The sender.</param> /// <param name="selectionChanged">Selection changed callabck. Triggered when user select a point with selec tool.</param> /// <param name="cursorMoved">Cursor moved callabck. Triggered when user move the mouse in chart area.</param> /// <param name="zoomChanged">Callback triggered when chart has /// zoomed in or out (and on first painting of the chart).</param> /// <remarks>Callback are optional (pass in null to ignore).</remarks> public static void EnableZoomAndPanControls(this Chart sender, CursorPositionChanged selectionChanged, CursorPositionChanged cursorMoved, ZoomChanged zoomChanged = null) { if (!ChartTool.ContainsKey(sender)) { ChartTool[sender] = new ChartData(sender); ChartData ptrChartData = ChartTool[sender]; ptrChartData.Backup(); ptrChartData.SelectionChangedCallback = selectionChanged; ptrChartData.CursorMovedCallback = cursorMoved; ptrChartData.ZoomChangedCallback = zoomChanged; //Populate Context menu Chart ptrChart = sender; if (ptrChart.ContextMenuStrip == null) { //Context menu is empty, use ChartContextMenuStrip directly ptrChart.ContextMenuStrip = new ContextMenuStrip(); ptrChart.ContextMenuStrip.Items.AddRange(ChartTool[ptrChart].MenuItems.ToArray()); } else { //User assigned context menu to chart. Merge current menu with ChartContextMenuStrip. ContextMenuStrip newMenu = new ContextMenuStrip(); newMenu.Items.AddRange(ChartTool[sender].MenuItems.ToArray()); foreach (object ptrItem in ChartTool[sender].ContextMenuStrip.Items) { if (ptrItem is ToolStripMenuItem) { newMenu.Items.Add(((ToolStripMenuItem)ptrItem).Clone()); } else if (ptrItem is ToolStripSeparator) { newMenu.Items.Add(new ToolStripSeparator()); } } newMenu.Items.Add(new ToolStripSeparator()); ptrChart.ContextMenuStrip = newMenu; ptrChart.ContextMenuStrip.AddHandlers(ChartTool[sender].ContextMenuStrip); } ptrChart.ContextMenuStrip.Opening += ChartContext_Opening; ptrChart.ContextMenuStrip.ItemClicked += ChartContext_ItemClicked; ptrChart.MouseDown += ChartControl_MouseDown; ptrChart.MouseMove += ChartControl_MouseMove; ptrChart.MouseUp += ChartControl_MouseUp; ptrChart.PostPaint += ChartOnPostPaint; // Necessary to kickstart ZoomChanged callback // The following is for testing out the built-in events. // They don't seem to be as reliable as just handling mouse up/move/down //ptrChart.CursorPositionChanging += (sender1, e) => // { // // Changed event isn't triggered with any zoom or select operations! From looking at the Cursor.cs code, it seems to be a bug. // // Changing event is raised twice, once for each cursor (X, Y) // var axis = e.Axis; // }; //ptrChart.SelectionRangeChanging += (o, args) => // { // // Changed event isn't triggered with any zoom or select operations! // // Neither is changed event... odd // Console.WriteLine("SelectionRangeChanging raised " + args.ToString()); // var axis = args.Axis; // var chartArea = args.ChartArea; // }; //Override settings. ChartArea ptrChartArea = ptrChart.ChartAreas[0]; ptrChartArea.CursorX.AutoScroll = false; ptrChartArea.CursorX.Interval = 1e-06; ptrChartArea.CursorY.AutoScroll = false; ptrChartArea.CursorY.Interval = 1e-06; ptrChartArea.AxisX.ScrollBar.Enabled = false; ptrChartArea.AxisX2.ScrollBar.Enabled = false; ptrChartArea.AxisY.ScrollBar.Enabled = false; ptrChartArea.AxisY2.ScrollBar.Enabled = false; SetChartControlState(sender, MSChartExtensionToolState.Select); } }
/// <summary> /// Enable Zoom and Pan Controls. /// </summary> /// <param name="sender">The sender.</param> /// <param name="selectionChanged">Selection changed callabck. Triggered when user select a point with selec tool.</param> /// <param name="cursorMoved">Cursor moved callabck. Triggered when user move the mouse in chart area.</param> /// <remarks>Callback are optional.</remarks> public static void EnableZoomAndPanControls(this Chart sender, CursorPositionChanged selectionChanged, CursorPositionChanged cursorMoved) { if (!ChartTool.ContainsKey(sender)) { ChartTool[sender] = new ChartData(sender); ChartData ptrChartData = ChartTool[sender]; ptrChartData.Backup(); ptrChartData.SelectionChangedCallback = selectionChanged; ptrChartData.CursorMovedCallback = cursorMoved; //Populate Context menu Chart ptrChart = sender; if (ptrChart.ContextMenuStrip == null) { //Context menu is empty, use ChartContextMenuStrip directly ptrChart.ContextMenuStrip = new ContextMenuStrip(); ptrChart.ContextMenuStrip.Items.AddRange(ChartTool[ptrChart].MenuItems.ToArray()); } else { //User assigned context menu to chart. Merge current menu with ChartContextMenuStrip. ContextMenuStrip newMenu = new ContextMenuStrip(); newMenu.Items.AddRange(ChartTool[sender].MenuItems.ToArray()); foreach (object ptrItem in ChartTool[sender].ContextMenuStrip.Items) { if (ptrItem is ToolStripMenuItem) { newMenu.Items.Add(((ToolStripMenuItem)ptrItem).Clone()); } else if (ptrItem is ToolStripSeparator) { newMenu.Items.Add(new ToolStripSeparator()); } } newMenu.Items.Add(new ToolStripSeparator()); ptrChart.ContextMenuStrip = newMenu; ptrChart.ContextMenuStrip.AddHandlers(ChartTool[sender].ContextMenuStrip); } ptrChart.ContextMenuStrip.Opening += ChartContext_Opening; ptrChart.ContextMenuStrip.ItemClicked += ChartContext_ItemClicked; ptrChart.MouseDown += ChartControl_MouseDown; ptrChart.MouseMove += ChartControl_MouseMove; ptrChart.MouseUp += ChartControl_MouseUp; ptrChart.KeyDown += ChartControl_KeyDown; //Override settings. ChartArea ptrChartArea = ptrChart.ChartAreas[0]; ptrChartArea.CursorX.AutoScroll = false; ptrChartArea.CursorX.Interval = 1e-06; ptrChartArea.CursorY.AutoScroll = false; ptrChartArea.CursorY.Interval = 1e-06; ptrChartArea.AxisX.ScrollBar.Enabled = false; ptrChartArea.AxisX2.ScrollBar.Enabled = false; ptrChartArea.AxisY.ScrollBar.Enabled = false; ptrChartArea.AxisY2.ScrollBar.Enabled = false; SetChartControlState(sender, MSChartExtensionToolState.Select); } }
private static void ChartControl_MouseUp(object sender, MouseEventArgs e) { if (e.Button != System.Windows.Forms.MouseButtons.Left) { return; } MouseDowned = false; Chart ptrChart = (Chart)sender; ChartArea ptrChartArea = ptrChart.ChartAreas[0]; ChartData data = GetDataForChart(ptrChart); MSChartExtensionToolState state = data.ToolState; switch (state) { case MSChartExtensionToolState.Zoom: case MSChartExtensionToolState.ZoomX: //Zoom area (Pixel) double XStart = ptrChartArea.CursorX.SelectionStart; double XEnd = ptrChartArea.CursorX.SelectionEnd; double YStart = ptrChartArea.CursorY.SelectionStart; double YEnd = ptrChartArea.CursorY.SelectionEnd; if ((XStart == XEnd) && (YStart == YEnd)) { return; } //Zoom area for X Axis double left = Math.Min(XStart, XEnd); double right = Math.Max(XStart, XEnd); double XMin = ptrChartArea.AxisX.ValueToPosition(left); double XMax = ptrChartArea.AxisX.ValueToPosition(right); //Zoom area for Y Axis double bottom = Math.Min(YStart, YEnd); double top = Math.Max(YStart, YEnd); double YMin = ptrChartArea.AxisY.ValueToPosition(bottom); double YMax = ptrChartArea.AxisY.ValueToPosition(top); // NOTE: left <= right, even if Axis.IsReversed //X-Axis ptrChartArea.AxisX.ScaleView.Zoom(left, right); ptrChartArea.AxisX2.ScaleView.Zoom( ptrChartArea.AxisX2.PositionToValue(XMin), ptrChartArea.AxisX2.PositionToValue(XMax)); //Y-Axis if (state == MSChartExtensionToolState.Zoom) { ptrChartArea.AxisY.ScaleView.Zoom(bottom, top); ptrChartArea.AxisY2.ScaleView.Zoom( ptrChartArea.AxisY2.PositionToValue(YMin), ptrChartArea.AxisY2.PositionToValue(YMax)); } //Clear selection (the following seem to be equivalent) ptrChartArea.CursorX.SetSelectionPosition(0, 0); ptrChartArea.CursorY.SetSelectionPosition(0, 0); //ptrChartArea.CursorX.SelectionStart = ptrChartArea.CursorX.SelectionEnd; //ptrChartArea.CursorY.SelectionStart = ptrChartArea.CursorY.SelectionEnd; //NOTE: At this point, the scaled view has already been updated to reflect zoom OnZoomChanged(ptrChart); break; case MSChartExtensionToolState.Pan: break; } }