using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using ScottPlot;
using ScottPlot.Plottable;
namespace TestProject
{
/// <summary>
/// 메인 폼
/// </summary>
public partial class MainForm : Form
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// 차트 1 십자선
/// </summary>
private Crosshair chart1Crosshair = null;
/// <summary>
/// 차트 2 수직선
/// </summary>
private VLine chart2VLine = null;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainForm()
/// <summary>
/// 생성자
/// </summary>
public MainForm()
{
InitializeComponent();
Random random = new Random(0);
OHLC[] chart1OHLCArray = DataGen.RandomStockPrices(null, 60, TimeSpan.FromDays(1));
double[] chart2XArray = chart1OHLCArray.Select(OHLC => OHLC.DateTime.ToOADate()).ToArray();
double[] chart2YArray = DataGen.Random(random, chart2XArray.Length, 10000, 50);
#region 차트 컨트롤 1을 설정한다.
this.chartControl1.Plot.XAxis.DateTimeFormat(true);
this.chartControl1.Plot.XAxis.Line(false);
this.chartControl1.Plot.XAxis.TickDensity(5);
this.chartControl1.Plot.XAxis.TickLabelStyle(rotation : 90);
this.chartControl1.Plot.XAxis.Ticks(false);
#endregion
#region 차트 컨트롤 1에 재무 플롯을 추가한다.
FinancePlot financePlot = this.chartControl1.Plot.AddCandlesticks(chart1OHLCArray);
#endregion
#region 차트 컨트롤 1에 십자선을 추가한다.
this.chart1Crosshair = this.chartControl1.Plot.AddCrosshair(0, 0);
this.chart1Crosshair.XAxisIndex = 0;
this.chart1Crosshair.YAxisIndex = 0;
this.chart1Crosshair.LineWidth = 1;
this.chart1Crosshair.LineStyle = LineStyle.Solid;
this.chart1Crosshair.VerticalLine.PositionLabelOppositeAxis = false;
this.chart1Crosshair.VerticalLine.PositionFormatter = position => DateTime.FromOADate(position).ToString("yyyy-MM-dd");
this.chart1Crosshair.HorizontalLine.PositionLabelOppositeAxis = false;
this.chart1Crosshair.HorizontalLine.PositionFormatter = position => position.ToString("#,##0.00");
this.chart1Crosshair.Color = Color.Red;
this.chart1Crosshair.IsVisible = false;
#endregion
#region 차트 컨트롤 2를 설정한다.
this.chartControl2.Plot.XAxis.DateTimeFormat(true);
this.chartControl2.Plot.XAxis.TickDensity(5);
this.chartControl2.Plot.XAxis.TickLabelStyle(rotation : 90);
#endregion
#region 차트 컨트롤 2에 막대 플롯을 추가한다.
BarPlot barPlot = this.chartControl2.Plot.AddBar(chart2YArray, chart2XArray);
#endregion
#region 차트 컨트롤 2에 수직선을 추가한다.
this.chart2VLine = this.chartControl2.Plot.AddVerticalLine(0, Color.Red, 1f, LineStyle.Solid);
this.chart2VLine.LineWidth = 1;
this.chart2VLine.IsVisible = false;
#endregion
#region 차트 컨트롤 2의 축을 차트 컨트롤 1의 축과 동기화한다.
this.chartControl2.Plot.SetAxisLimitsX(this.chartControl1.Plot.XAxis.Dims.Min, this.chartControl1.Plot.XAxis.Dims.Max);
this.chartControl2.Plot.AxisAutoY();
#endregion
#region 이벤트를 설정한다.
this.chartControl1.AxesChanged += chartControl1_AxesChanged;
this.chartControl1.MouseEnter += chartControl1_MouseEnter;
this.chartControl1.MouseMove += chartControl1_MouseMove;
this.chartControl1.MouseLeave += chartControl1_MouseLeave;
this.chartControl2.AxesChanged += chartControl2_AxesChanged;
this.chartControl2.MouseEnter += chartControl2_MouseEnter;
this.chartControl2.MouseMove += chartControl2_MouseMove;
this.chartControl2.MouseLeave += chartControl2_MouseLeave;
#endregion
this.chartControl1.Plot.YAxis.SetSizeLimit(min : 50, max : 50);
this.chartControl2.Plot.YAxis.SetSizeLimit(min : 50, max : 50);
this.chartControl1.Refresh();
this.chartControl2.Refresh();
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Private
#region 차트 컨트롤 1 축 변경시 처리하기 - chartControl1_AxesChanged(sender, e)
/// <summary>
/// 차트 컨트롤 1 축 변경시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void chartControl1_AxesChanged(object sender, EventArgs e)
{
AxisLimits chart1AxisLimits = this.chartControl1.Plot.GetAxisLimits();
AxisLimits chart2AxisLimits = this.chartControl2.Plot.GetAxisLimits();
AxisLimits newChart2AxisLimits = new AxisLimits
(
chart1AxisLimits.XMin,
chart1AxisLimits.XMax,
chart2AxisLimits.YMin,
chart2AxisLimits.YMax
);
this.chartControl2.Configuration.AxesChangedEventEnabled = false;
this.chartControl2.Plot.SetAxisLimits(newChart2AxisLimits);
this.chartControl2.Render();
this.chartControl2.Configuration.AxesChangedEventEnabled = true;
}
#endregion
#region 차트 컨트롤 1 마우스 진입시 처리하기 - chartControl1_MouseEnter(sender, e)
/// <summary>
/// 차트 컨트롤 1 마우스 진입시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void chartControl1_MouseEnter(object sender, EventArgs e)
{
if(this.chart1Crosshair != null)
{
this.chart1Crosshair.IsVisible = true;
this.chart2VLine.IsVisible = true;
this.chartControl1.Refresh();
this.chartControl2.Refresh();
}
}
#endregion
#region 차트 컨트롤 1 마우스 이동시 처리하기 - chartControl1_MouseMove(sender, e)
/// <summary>
/// 차트 컨트롤 1 마우스 이동시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void chartControl1_MouseMove(object sender, MouseEventArgs e)
{
if(this.chart1Crosshair != null)
{
(double coordinateX, double coordinateY) = this.chartControl1.GetMouseCoordinates(0, 0);
this.chart1Crosshair.X = coordinateX;
this.chart1Crosshair.Y = coordinateY;
this.chart2VLine.X = coordinateX;
this.chartControl1.Refresh(lowQuality : true, skipIfCurrentlyRendering : true);
this.chartControl2.Refresh(lowQuality : true, skipIfCurrentlyRendering : true);
}
}
#endregion
#region 차트 컨트롤 1 마우스 이탈시 처리하기 - chartControl1_MouseLeave(sender, e)
/// <summary>
/// 차트 컨트롤 1 마우스 이탈시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void chartControl1_MouseLeave(object sender, EventArgs e)
{
if(this.chart1Crosshair != null)
{
this.chart1Crosshair.IsVisible = false;
this.chart2VLine.IsVisible = false;
this.chartControl1.Refresh();
this.chartControl2.Refresh();
}
}
#endregion
#region 차트 컨트롤 2 축 변경시 처리하기 - chartControl2_AxesChanged(sender, e)
/// <summary>
/// 차트 컨트롤 2 축 변경시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void chartControl2_AxesChanged(object sender, EventArgs e)
{
AxisLimits chart1AxisLimits = this.chartControl1.Plot.GetAxisLimits();
AxisLimits chart2AxisLimits = this.chartControl2.Plot.GetAxisLimits();
AxisLimits newChart1AxisLimits = new AxisLimits
(
chart2AxisLimits.XMin,
chart2AxisLimits.XMax,
chart1AxisLimits.YMin,
chart1AxisLimits.YMax
);
this.chartControl1.Configuration.AxesChangedEventEnabled = false;
this.chartControl1.Plot.SetAxisLimits(newChart1AxisLimits);
this.chartControl1.Render();
this.chartControl1.Configuration.AxesChangedEventEnabled = true;
}
#endregion
#region 차트 컨트롤 2 마우스 진입시 처리하기 - chartControl2_MouseEnter(sender, e)
/// <summary>
/// 차트 컨트롤 2 마우스 진입시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void chartControl2_MouseEnter(object sender, EventArgs e)
{
if(this.chart2VLine != null)
{
this.chart1Crosshair.IsVisible = true;
this.chart2VLine.IsVisible = true;
this.chartControl1.Refresh();
this.chartControl2.Refresh();
}
}
#endregion
#region 차트 컨트롤 2 마우스 이동시 처리하기 - chartControl2_MouseMove(sender, e)
/// <summary>
/// 차트 컨트롤 2 마우스 이동시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void chartControl2_MouseMove(object sender, MouseEventArgs e)
{
if(this.chart2VLine != null)
{
(double coordinateX, double _) = this.chartControl2.GetMouseCoordinates(0, 0);
this.chart1Crosshair.X = coordinateX;
this.chart2VLine.X = coordinateX;
this.chartControl1.Refresh(lowQuality : true, skipIfCurrentlyRendering : true);
this.chartControl2.Refresh(lowQuality : true, skipIfCurrentlyRendering : true);
}
}
#endregion
#region 차트 컨트롤 2 마우스 이탈시 처리하기 - chartControl2_MouseLeave(sender, e)
/// <summary>
/// 차트 컨트롤 2 마우스 이탈시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void chartControl2_MouseLeave(object sender, EventArgs e)
{
if(this.chart2VLine != null)
{
this.chart1Crosshair.IsVisible = false;
this.chart2VLine.IsVisible = false;
this.chartControl1.Refresh();
this.chartControl2.Refresh();
}
}
#endregion
}
}