Как включить масштабирование в элементе управления диаграммой Microsoft с помощью колесика мыши

Я использую элемент управления Microsoft Chart в своем проекте и хочу включить функцию масштабирования в элементе управления Chart с помощью колесика мыши, как я могу этого добиться?

но пользователю не нужно нажимать на график. Это должно быть так, как если бы положение мыши на моей диаграмме было больше, чем когда эта точка прокручивается колесом мыши, она может увеличивать / уменьшать масштаб.

3 ответа

Вы хотите использовать MouseWheel событие.

Сначала сделайте масштабирование обеих осей вашей диаграммы:

chart1.ChartAreas[0].AxisX.ScaleView.Zoomable = true;
chart1.ChartAreas[0].AxisY.ScaleView.Zoomable = true;

И назначьте событие:

chart1.MouseWheel += chart1_MouseWheel;

Затем в обработчике событий:

private void chart1_MouseWheel(object sender, MouseEventArgs e)
{
    var chart = (Chart)sender;
    var xAxis = chart.ChartAreas[0].AxisX;
    var yAxis = chart.ChartAreas[0].AxisY;

    try
    {
        if (e.Delta < 0) // Scrolled down.
        {
            xAxis.ScaleView.ZoomReset();
            yAxis.ScaleView.ZoomReset();
        }
        else if (e.Delta > 0) // Scrolled up.
        {
            var xMin = xAxis.ScaleView.ViewMinimum;
            var xMax = xAxis.ScaleView.ViewMaximum;
            var yMin = yAxis.ScaleView.ViewMinimum;
            var yMax = yAxis.ScaleView.ViewMaximum;

            var posXStart = xAxis.PixelPositionToValue(e.Location.X) - (xMax - xMin) / 4;
            var posXFinish = xAxis.PixelPositionToValue(e.Location.X) + (xMax - xMin) / 4;
            var posYStart = yAxis.PixelPositionToValue(e.Location.Y) - (yMax - yMin) / 4;
            var posYFinish = yAxis.PixelPositionToValue(e.Location.Y) + (yMax - yMin) / 4;

            xAxis.ScaleView.Zoom(posXStart, posXFinish);
            yAxis.ScaleView.Zoom(posYStart, posYFinish);
        }
    }
    catch { }            
}

e.Delta свойство говорит вам, сколько колесных "свитков" вы сделали, и может быть полезно.
Прокрутка вообще уменьшит весь путь.

Вероятно, есть более чистый способ сделать это, но это так. Надеюсь это поможет!

Я изменил код сверху и добавил обратное масштабирование с помощью Stack.

private class ZoomFrame
{
    public double XStart { get; set; }
    public double XFinish { get; set; }
    public double YStart { get; set; }
    public double YFinish { get; set; }
}

private readonly Stack<ZoomFrame> _zoomFrames = new Stack<ZoomFrame>();
private void chart1_MouseWheel(object sender, MouseEventArgs e)
{
    var chart = (Chart)sender;
    var xAxis = chart.ChartAreas[0].AxisX;
    var yAxis = chart.ChartAreas[0].AxisY;

    try
    {
        if (e.Delta < 0)
        {
            if (0 < _zoomFrames.Count)
            {
                var frame = _zoomFrames.Pop();
                if (_zoomFrames.Count == 0)
                {
                    xAxis.ScaleView.ZoomReset();
                    yAxis.ScaleView.ZoomReset();
                }
                else
                {
                    xAxis.ScaleView.Zoom(frame.XStart, frame.XFinish);
                    yAxis.ScaleView.Zoom(frame.YStart, frame.YFinish);
                }
            }
        }
        else if (e.Delta > 0)
        {
            var xMin = xAxis.ScaleView.ViewMinimum;
            var xMax = xAxis.ScaleView.ViewMaximum;
            var yMin = yAxis.ScaleView.ViewMinimum;
            var yMax = yAxis.ScaleView.ViewMaximum;

            _zoomFrames.Push(new ZoomFrame { XStart = xMin, XFinish = xMax, YStart = yMin, YFinish = yMax });

            var posXStart = xAxis.PixelPositionToValue(e.Location.X) - (xMax - xMin) / 4;
            var posXFinish = xAxis.PixelPositionToValue(e.Location.X) + (xMax - xMin) / 4;
            var posYStart = yAxis.PixelPositionToValue(e.Location.Y) - (yMax - yMin) / 4;
            var posYFinish = yAxis.PixelPositionToValue(e.Location.Y) + (yMax - yMin) / 4;

            xAxis.ScaleView.Zoom(posXStart, posXFinish);
            yAxis.ScaleView.Zoom(posYStart, posYFinish);
        }
    }
    catch { }         
}

Надеюсь это поможет!

Я модифицировал код сверху и добавил обратное масштабирование. Поэтому, когда вы поворачиваете колесо мыши назад, диаграмма уменьшается. Также я не рекомендую использовать 2^n в качестве делителя интервала, потому что это вызывает отставание.

numberOfZoom - counter of Zooming
private void Chart1_MouseWheel(object sender, MouseEventArgs e)
    {
        var chart = (Chart)sender;
        var xAxis = chart.ChartAreas[0].AxisX;
        var yAxis = chart.ChartAreas[0].AxisY;

        var xMin = xAxis.ScaleView.ViewMinimum;
        var xMax = xAxis.ScaleView.ViewMaximum;
        var yMin = yAxis.ScaleView.ViewMinimum;
        var yMax = yAxis.ScaleView.ViewMaximum;

        int IntervalX = 3;
        int IntervalY = 3;
        try
        {
            if (e.Delta < 0 && numberOfZoom > 0) // Scrolled down.
            {
                var posXStart = xAxis.PixelPositionToValue(e.Location.X) - IntervalX *2/ Math.Pow(2, numberOfZoom);
                var posXFinish = xAxis.PixelPositionToValue(e.Location.X) + IntervalX *2/ Math.Pow(2, numberOfZoom);
                var posYStart = yAxis.PixelPositionToValue(e.Location.Y) - IntervalY*2 / Math.Pow(2, numberOfZoom);
                var posYFinish = yAxis.PixelPositionToValue(e.Location.Y) + IntervalY*2 / Math.Pow(2, numberOfZoom);

                if (posXStart < 0) posXStart = 0;
                if (posYStart < 0) posYStart = 0;
                if (posYFinish > yAxis.Maximum) posYFinish = yAxis.Maximum;
                if (posXFinish > xAxis.Maximum) posYFinish = xAxis.Maximum;
                xAxis.ScaleView.Zoom(posXStart, posXFinish);
                yAxis.ScaleView.Zoom(posYStart, posYFinish);
                numberOfZoom--;
            }else if (e.Delta < 0 && numberOfZoom == 0) //Last scrolled dowm
            {
                yAxis.ScaleView.ZoomReset();
                xAxis.ScaleView.ZoomReset();
            }
            else if (e.Delta > 0) // Scrolled up.
            {

                var posXStart = xAxis.PixelPositionToValue(e.Location.X) - IntervalX  / Math.Pow(2, numberOfZoom);
                var posXFinish = xAxis.PixelPositionToValue(e.Location.X) + IntervalX / Math.Pow(2, numberOfZoom);
                var posYStart = yAxis.PixelPositionToValue(e.Location.Y) - IntervalY  / Math.Pow(2, numberOfZoom);
                var posYFinish = yAxis.PixelPositionToValue(e.Location.Y) + IntervalY  / Math.Pow(2, numberOfZoom);

                xAxis.ScaleView.Zoom(posXStart, posXFinish);
                yAxis.ScaleView.Zoom(posYStart, posYFinish);
                numberOfZoom++;
            }

            if (numberOfZoom < 0) numberOfZoom = 0;
        }
        catch { }
    }

Ваааа, опоздал на вечеринку, но у меня сегодня был этот вызов. Я уверен, что следующее можно улучшить, но это то, что я придумал. Я протестировал это с.net 4.5.2 и 4.6, поэтому я не уверен, что он работает со старыми фреймворками.

Я соединил пару ответов из прошлого и сделал следующее:

using System;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace ExampleApp
{
    public partial class Form1 : Form
    {
        private int FZoomLevel = 0;

        public Form1()
        {
            InitializeComponent();
            chart1.MouseWheel += Chart1_MouseWheel;
        }

        private void Chart1_MouseEnter(object sender, EventArgs e)
        {
            if (!chart1.Focused)
                chart1.Focus();
        }

        private void Chart1_MouseLeave(object sender, EventArgs e)
        {
            if (chart1.Focused)
                chart1.Parent.Focus();
        }

        private void Chart1_MouseWheel(object sender, MouseEventArgs e)
        {
            try {
                Axis xAxis = chart1.ChartAreas[0].AxisX;
                double xMin = xAxis.ScaleView.ViewMinimum;
                double xMax = xAxis.ScaleView.ViewMaximum;
                double xPixelPos = xAxis.PixelPositionToValue(e.Location.X);

                if (e.Delta < 0 && FZoomLevel > 0) {
                    // Scrolled down, meaning zoom out
                    if (--FZoomLevel <= 0) {
                        FZoomLevel = 0;
                        xAxis.ScaleView.ZoomReset();
                    } else {
                        double xStartPos = Math.Max(xPixelPos - (xPixelPos - xMin) * CZoomScale, 0);
                        double xEndPos = Math.Min(xStartPos + (xMax - xMin) * CZoomScale, xAxis.Maximum);
                        xAxis.ScaleView.Zoom(xStartPos, xEndPos);
                    }
                } else if (e.Delta > 0) {
                    // Scrolled up, meaning zoom in
                    double xStartPos = Math.Max(xPixelPos - (xPixelPos - xMin) / CZoomScale, 0);
                    double xEndPos = Math.Min(xStartPos + (xMax - xMin) / CZoomScale, xAxis.Maximum);
                    xAxis.ScaleView.Zoom(xStartPos, xEndPos);
                    FZoomLevel++;
                }
            } catch { }
        }
    }
}
Другие вопросы по тегам