[Windows Forms - C# version] NetWinCharts\CSharpWinCharts\frmxyzoomscroll.cs
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using ChartDirector;
namespace CSharpChartExplorer
{
public partial class FrmXYZoomScroll : Form
{
// XY data points for the chart
private double[] dataX0;
private double[] dataY0;
private double[] dataX1;
private double[] dataY1;
private double[] dataX2;
private double[] dataY2;
public FrmXYZoomScroll()
{
InitializeComponent();
}
private void FrmXYZoomScroll_Load(object sender, EventArgs e)
{
// Load the data
loadData();
// Trigger the ViewPortChanged event to draw the chart
winChartViewer1.updateViewPort(true, true);
// Draw the full thumbnail chart for the ViewPortControl
drawFullChart(viewPortControl1, winChartViewer1);
}
//
// Load the data
//
private void loadData()
{
//
// For simplicity, in this demo, we just use hard coded data.
//
dataX0 = new double[] { 10, 15, 6, -12, 14, -8, 13, -3, 16, 12, 10.5, -7, 3, -10, -5, 2, 5 };
dataY0 = new double[] {130, 150, 80, 110, -110, -105, -130, -15, -170, 125, 125, 60, 25, 150,
150, 15, 120};
dataX1 = new double[] { 6, 7, -4, 3.5, 7, 8, -9, -10, -12, 11, 8, -3, -2, 8, 4, -15, 15 };
dataY1 = new double[] {65, -40, -40, 45, -70, -80, 80, 10, -100, 105, 60, 50, 20, 170, -25, 50,
75};
dataX2 = new double[] { -10, -12, 11, 8, 6, 12, -4, 3.5, 7, 8, -9, 3, -13, 16, -7.5, -10, -15 };
dataY2 = new double[] {65, -80, -40, 45, -70, -80, 80, 90, -100, 105, 60, -75, -150, -40, 120,
-50, -30};
}
//
// The ViewPortChanged event handler. This event occurs if the user scrolls or zooms in
// or out the chart by dragging or clicking on the chart. It can also be triggered by
// calling WinChartViewer.updateViewPort.
//
private void winChartViewer1_ViewPortChanged(object sender, WinViewPortEventArgs e)
{
// In addition to updating the chart, we may also need to update other controls that
// changes based on the view port.
updateControls(winChartViewer1);
// Update the chart if necessary
if (e.NeedUpdateChart)
drawChart(winChartViewer1);
// Update the image map if necessary
if (e.NeedUpdateImageMap)
updateImageMap(winChartViewer1);
}
//
// Update controls when the view port changed
//
private void updateControls(WinChartViewer viewer)
{
// Synchronize the zoom bar value with the view port width/height
zoomBar.Value = (int)Math.Round(Math.Min(viewer.ViewPortWidth, viewer.ViewPortHeight) *
zoomBar.Maximum);
}
//
// Draw the chart and display it in the given viewer
//
private void drawChart(WinChartViewer viewer)
{
// Create an XYChart object 500 x 480 pixels in size, with the same background color
// as the container
XYChart c = new XYChart(500, 480, Chart.CColor(BackColor));
// Set the plotarea at (50, 40) and of size 400 x 400 pixels. Use light grey (c0c0c0)
// horizontal and vertical grid lines. Set 4 quadrant coloring, where the colors of
// the quadrants alternate between lighter and deeper grey (dddddd/eeeeee).
c.setPlotArea(50, 40, 400, 400, -1, -1, -1, 0xc0c0c0, 0xc0c0c0
).set4QBgColor(0xdddddd, 0xeeeeee, 0xdddddd, 0xeeeeee, 0x000000);
// Enable clipping mode to clip the part of the data that is outside the plot area.
c.setClipping();
// Set 4 quadrant mode, with both x and y axes symetrical around the origin
c.setAxisAtOrigin(Chart.XYAxisAtOrigin, Chart.XAxisSymmetric + Chart.YAxisSymmetric);
// Add a legend box at (450, 40) (top right corner of the chart) with vertical layout
// and 8 pts Arial Bold font. Set the background color to semi-transparent grey.
LegendBox b = c.addLegend(450, 40, true, "Arial Bold", 8);
b.setAlignment(Chart.TopRight);
b.setBackground(0x40dddddd);
// Add a titles to axes
c.xAxis().setTitle("Alpha Index");
c.yAxis().setTitle("Beta Index");
// Set axes width to 2 pixels
c.xAxis().setWidth(2);
c.yAxis().setWidth(2);
// The default ChartDirector settings has a denser y-axis grid spacing and less-dense
// x-axis grid spacing. In this demo, we want the tick spacing to be symmetrical.
// We use around 50 pixels between major ticks and 25 pixels between minor ticks.
c.xAxis().setTickDensity(50, 25);
c.yAxis().setTickDensity(50, 25);
//
// In this example, we represent the data by scatter points. If you want to represent
// the data by somethings else (lines, bars, areas, floating boxes, etc), just modify
// the code below to use the layer type of your choice.
//
// Add scatter layer, using 11 pixels red (ff33333) X shape symbols
c.addScatterLayer(dataX0, dataY0, "Group A", Chart.Cross2Shape(), 11, 0xff3333);
// Add scatter layer, using 11 pixels green (33ff33) circle symbols
c.addScatterLayer(dataX1, dataY1, "Group B", Chart.CircleShape, 11, 0x33ff33);
// Add scatter layer, using 11 pixels blue (3333ff) triangle symbols
c.addScatterLayer(dataX2, dataY2, "Group C", Chart.TriangleSymbol, 11, 0x3333ff);
//
// In this example, we have not explicitly configured the full x and y range. In this case, the
// first time syncLinearAxisWithViewPort is called, ChartDirector will auto-scale the axis and
// assume the resulting range is the full range. In subsequent calls, ChartDirector will set the
// axis range based on the view port and the full range.
//
viewer.syncLinearAxisWithViewPort("x", c.xAxis());
viewer.syncLinearAxisWithViewPort("y", c.yAxis());
// We need to update the track line too. If the mouse is moving on the chart (eg. if
// the user drags the mouse on the chart to scroll it), the track line will be updated
// in the MouseMovePlotArea event. Otherwise, we need to update the track line here.
if ((!viewer.IsInMouseMoveEvent) && viewer.IsMouseOnPlotArea)
crossHair(c, viewer.PlotAreaMouseX, viewer.PlotAreaMouseY);
// Set the chart image to the WinChartViewer
viewer.Chart = c;
}
//
// Draw the full thumbnail chart and display it in the given ViewPortControl
//
private void drawFullChart(WinViewPortControl vpc, WinChartViewer viewer)
{
// Create an XYChart object of the same size as the Viewport Control
XYChart c = new XYChart(viewPortControl1.ClientSize.Width, viewPortControl1.ClientSize.Height);
// Set the plotarea to cover the entire chart. Disable grid lines by setting their colors
// to transparent. Set 4 quadrant coloring, where the colors of the quadrants alternate
// between lighter and deeper grey (dddddd/eeeeee).
c.setPlotArea(0, 0, c.getWidth() - 1, c.getHeight() - 1, -1, -1, 0xff0000, Chart.Transparent,
Chart.Transparent).set4QBgColor(0xdddddd, 0xeeeeee, 0xdddddd, 0xeeeeee, 0x000000);
// Set 4 quadrant mode, with both x and y axes symetrical around the origin
c.setAxisAtOrigin(Chart.XYAxisAtOrigin, Chart.XAxisSymmetric + Chart.YAxisSymmetric);
// The x and y axis scales reflect the full range of the view port
c.xAxis().setLinearScale(viewer.getValueAtViewPort("x", 0), viewer.getValueAtViewPort("x", 1),
Chart.NoValue);
c.yAxis().setLinearScale(viewer.getValueAtViewPort("y", 0), viewer.getValueAtViewPort("y", 1),
Chart.NoValue);
// Add scatter layer, using 3 pixels red (ff33333) X shape symbols
c.addScatterLayer(dataX0, dataY0, "Group A", Chart.Cross2Shape(), 3, 0xff3333, 0xff3333);
// Add scatter layer, using 3 pixels green (33ff33) circle symbols
c.addScatterLayer(dataX1, dataY1, "Group B", Chart.CircleShape, 3, 0x33ff33, 0x33ff33);
// Add scatter layer, using 3 pixels blue (3333ff) triangle symbols
c.addScatterLayer(dataX2, dataY2, "Group C", Chart.TriangleSymbol, 3, 0x3333ff, 0x3333ff);
// Set the chart image to the WinChartViewer
vpc.Chart = c;
}
//
// Update the image map
//
private void updateImageMap(WinChartViewer viewer)
{
// Include tool tip for the chart
if (viewer.ImageMap == null)
{
viewer.ImageMap = viewer.Chart.getHTMLImageMap("clickable", "",
"title='[{dataSetName}] Alpha = {x}, Beta = {value}'");
}
}
//
// ClickHotSpot event handler. In this demo, we just display the hot spot parameters in a pop up
// dialog.
//
private void winChartViewer1_ClickHotSpot(object sender, WinHotSpotEventArgs e)
{
// We show the pop up dialog only when the mouse action is not in zoom-in or zoom-out mode.
if ((winChartViewer1.MouseUsage != WinChartMouseUsage.ZoomIn)
&& (winChartViewer1.MouseUsage != WinChartMouseUsage.ZoomOut))
new ParamViewer().Display(sender, e);
}
//
// Pointer (Drag to Scroll) button event handler
//
private void pointerPB_CheckedChanged(object sender, EventArgs e)
{
if (((RadioButton)sender).Checked)
winChartViewer1.MouseUsage = WinChartMouseUsage.ScrollOnDrag;
}
//
// Zoom In button event handler
//
private void zoomInPB_CheckedChanged(object sender, EventArgs e)
{
if (((RadioButton)sender).Checked)
winChartViewer1.MouseUsage = WinChartMouseUsage.ZoomIn;
}
//
// Zoom Out button event handler
//
private void zoomOutPB_CheckedChanged(object sender, EventArgs e)
{
if (((RadioButton)sender).Checked)
winChartViewer1.MouseUsage = WinChartMouseUsage.ZoomOut;
}
//
// Save button event handler
//
private void savePB_Click(object sender, EventArgs e)
{
// The standard Save File dialog
SaveFileDialog fileDlg = new SaveFileDialog();
fileDlg.Filter = "PNG (*.png)|*.png|JPG (*.jpg)|*.jpg|GIF (*.gif)|*.gif|BMP (*.bmp)|*.bmp|" +
"SVG (*.svg)|*.svg|PDF (*.pdf)|*.pdf";
fileDlg.FileName = "chartdirector_demo";
if (fileDlg.ShowDialog() != DialogResult.OK)
return;
// Save the chart
if (null != winChartViewer1.Chart)
winChartViewer1.Chart.makeChart(fileDlg.FileName);
}
//
// ValueChanged event handler for zoomBar. Zoom in around the center point and try to
// maintain the aspect ratio
//
private void zoomBar_ValueChanged(object sender, EventArgs e)
{
if (!winChartViewer1.IsInViewPortChangedEvent)
{
//Remember the center point
double centerX = winChartViewer1.ViewPortLeft + winChartViewer1.ViewPortWidth / 2;
double centerY = winChartViewer1.ViewPortTop + winChartViewer1.ViewPortHeight / 2;
//Aspect ratio and zoom factor
double aspectRatio = winChartViewer1.ViewPortWidth / winChartViewer1.ViewPortHeight;
double zoomTo = ((double)zoomBar.Value) / zoomBar.Maximum;
//Zoom while respecting the aspect ratio
winChartViewer1.ViewPortWidth = zoomTo * Math.Max(1, aspectRatio);
winChartViewer1.ViewPortHeight = zoomTo * Math.Max(1, 1 / aspectRatio);
//Adjust ViewPortLeft and ViewPortTop to keep center point unchanged
winChartViewer1.ViewPortLeft = centerX - winChartViewer1.ViewPortWidth / 2;
winChartViewer1.ViewPortTop = centerY - winChartViewer1.ViewPortHeight / 2;
//update the chart, but no need to update the image map yet, as the chart is still
//zooming and is unstable
winChartViewer1.updateViewPort(true, false);
}
}
//
// Draw track cursor when mouse is moving over plotarea, and update image map if necessary
//
private void winChartViewer1_MouseMovePlotArea(object sender, MouseEventArgs e)
{
WinChartViewer viewer = (WinChartViewer)sender;
// Draw crosshair track cursor
crossHair((XYChart)viewer.Chart, viewer.PlotAreaMouseX, viewer.PlotAreaMouseY);
viewer.updateDisplay();
// Hide the track cursor when the mouse leaves the plot area
viewer.removeDynamicLayer("MouseLeavePlotArea");
// Update image map if necessary. If the mouse is still dragging, the chart is still
// updating and not confirmed, so there is no need to set up the image map.
if (!viewer.IsMouseDragging)
updateImageMap(viewer);
}
//
// Draw cross hair cursor with axis labels
//
private void crossHair(XYChart c, int mouseX, int mouseY)
{
// Clear the current dynamic layer and get the DrawArea object to draw on it.
DrawArea d = c.initDynamicLayer();
// The plot area object
PlotArea plotArea = c.getPlotArea();
// Draw a vertical line and a horizontal line as the cross hair
d.vline(plotArea.getTopY(), plotArea.getBottomY(), mouseX, d.dashLineColor(0x000000, 0x0101));
d.hline(plotArea.getLeftX(), plotArea.getRightX(), mouseY, d.dashLineColor(0x000000, 0x0101));
// Draw y-axis label
string label = "<*block,bgColor=FFFFDD,margin=3,edgeColor=000000*>" + c.formatValue(c.getYValue(
mouseY, c.yAxis()), "{value|P4}") + "<*/*>";
TTFText t = d.text(label, "Arial Bold", 8);
t.draw(plotArea.getLeftX() - 5, mouseY, 0x000000, Chart.Right);
// Draw x-axis label
label = "<*block,bgColor=FFFFDD,margin=3,edgeColor=000000*>" + c.formatValue(c.getXValue(mouseX),
"{value|P4}") + "<*/*>";
t = d.text(label, "Arial Bold", 8);
t.draw(mouseX, plotArea.getBottomY() + 5, 0x000000, Chart.Top);
}
}
}
[Windows Forms - VB Version] NetWinCharts\VBNetWinCharts\frmxyzoomscroll.vb
Imports ChartDirector
Public Class FrmXYZoomScroll
' Data arrays
Dim dataX0 As Double()
Dim dataY0 As Double()
Dim dataX1 As Double()
Dim dataY1 As Double()
Dim dataX2 As Double()
Dim dataY2 As Double()
Private Sub FrmXYZoomScroll_Load(ByVal sender As Object, ByVal e As EventArgs) _
Handles MyBase.Load
' Load the data
loadData()
' Trigger the ViewPortChanged event to draw the chart
winChartViewer1.updateViewPort(True, True)
' Draw the full thumbnail chart for the ViewPortControl
drawFullChart(viewPortControl1, winChartViewer1)
End Sub
'
' Load the data
'
Private Sub loadData()
'
' For simplicity, in this demo, we just use hard coded data.
'
dataX0 = New Double() {10, 15, 6, -12, 14, -8, 13, -3, 16, 12, 10.5, -7, 3, -10, -5, 2, 5}
dataY0 = New Double() {130, 150, 80, 110, -110, -105, -130, -15, -170, 125, 125, 60, 25, 150, _
150, 15, 120}
dataX1 = New Double() {6, 7, -4, 3.5, 7, 8, -9, -10, -12, 11, 8, -3, -2, 8, 4, -15, 15}
dataY1 = New Double() {65, -40, -40, 45, -70, -80, 80, 10, -100, 105, 60, 50, 20, 170, -25, 50, 75}
dataX2 = New Double() {-10, -12, 11, 8, 6, 12, -4, 3.5, 7, 8, -9, 3, -13, 16, -7.5, -10, -15}
dataY2 = New Double() {65, -80, -40, 45, -70, -80, 80, 90, -100, 105, 60, -75, -150, -40, 120, _
-50, -30}
End Sub
'
' The ViewPortChanged event handler. This event occurs if the user scrolls or zooms in
' or out the chart by dragging or clicking on the chart. It can also be triggered by
' calling WinChartViewer.updateViewPort.
'
Private Sub winChartViewer1_ViewPortChanged(ByVal sender As Object, _
ByVal e As WinViewPortEventArgs) Handles winChartViewer1.ViewPortChanged
' In addition to updating the chart, we may also need to update other controls that
' changes based on the view port.
updateControls(winChartViewer1)
' Update the chart if necessary
If e.NeedUpdateChart Then
drawChart(winChartViewer1)
End If
' Update the image map if necessary
If e.NeedUpdateImageMap Then
updateImageMap(winChartViewer1)
End If
End Sub
'
' Update controls when the view port changed
'
Private Sub updateControls(ByVal viewer As WinChartViewer)
' Synchronize the zoom bar value with the view port width/height
zoomBar.Value = Math.Round(Math.Min(viewer.ViewPortWidth, viewer.ViewPortHeight) * zoomBar.Maximum)
End Sub
'
' Draw the chart.
'
Private Sub drawChart(ByVal viewer As WinChartViewer)
' Create an XYChart object 500 x 480 pixels in size, with the same background color
' as the container
Dim c As XYChart = New XYChart(500, 480, Chart.CColor(BackColor))
' Set the plotarea at (50, 40) and of size 400 x 400 pixels. Use light grey (c0c0c0)
' horizontal and vertical grid lines. Set 4 quadrant coloring, where the colors of
' the quadrants alternate between lighter and deeper grey (dddddd/eeeeee).
c.setPlotArea(50, 40, 400, 400, -1, -1, -1, &HC0C0C0, &HC0C0C0 _
).set4QBgColor(&HDDDDDD, &HEEEEEE, &HDDDDDD, &HEEEEEE, &H0)
' Enable clipping mode to clip the part of the data that is outside the plot area.
c.setClipping()
' Set 4 quadrant mode, with both x and y axes symetrical around the origin
c.setAxisAtOrigin(Chart.XYAxisAtOrigin, Chart.XAxisSymmetric + Chart.YAxisSymmetric)
' Add a legend box at (450, 40) (top right corner of the chart) with vertical layout
' and 8 pts Arial Bold font. Set the background color to semi-transparent grey.
Dim b As LegendBox = c.addLegend(450, 40, True, "Arial Bold", 8)
b.setAlignment(Chart.TopRight)
b.setBackground(&H40DDDDDD)
' Add a titles to axes
c.xAxis().setTitle("Alpha Index")
c.yAxis().setTitle("Beta Index")
' Set axes width to 2 pixels
c.xAxis().setWidth(2)
c.yAxis().setWidth(2)
' The default ChartDirector settings has a denser y-axis grid spacing and less-dense
' x-axis grid spacing. In this demo, we want the tick spacing to be symmetrical.
' We use around 50 pixels between major ticks and 25 pixels between minor ticks.
c.xAxis().setTickDensity(50, 25)
c.yAxis().setTickDensity(50, 25)
'
' In this example, we represent the data by scatter points. If you want to represent
' the data by somethings else (lines, bars, areas, floating boxes, etc), just modify
' the code below to use the layer type of your choice.
'
' Add scatter layer, using 11 pixels red (ff33333) X shape symbols
c.addScatterLayer(dataX0, dataY0, "Group A", Chart.Cross2Shape(), 11, &HFF3333)
' Add scatter layer, using 11 pixels green (33ff33) circle symbols
c.addScatterLayer(dataX1, dataY1, "Group B", Chart.CircleShape, 11, &H33FF33)
' Add scatter layer, using 11 pixels blue (3333ff) triangle symbols
c.addScatterLayer(dataX2, dataY2, "Group C", Chart.TriangleSymbol, 11, &H3333FF)
'
' In this example, we have not explicitly configured the full x and y range. In this case, the
' first time syncLinearAxisWithViewPort is called, ChartDirector will auto-scale the axis and
' assume the resulting range is the full range. In subsequent calls, ChartDirector will set the
' axis range based on the view port and the full range.
'
viewer.SyncLinearAxisWithViewPort("x", c.xAxis())
viewer.SyncLinearAxisWithViewPort("y", c.yAxis())
' We need to update the track line too. If the mouse is moving on the chart (eg. if
' the user drags the mouse on the chart to scroll it), the track line will be updated
' in the MouseMovePlotArea event. Otherwise, we need to update the track line here.
If (Not viewer.IsInMouseMoveEvent) And viewer.IsMouseOnPlotArea Then
crossHair(c, viewer.PlotAreaMouseX, viewer.PlotAreaMouseY)
End If
' Set the chart image to the WinChartViewer
viewer.Chart = c
End Sub
'
' Draw the full thumbnail chart and display it in the given ViewPortControl
'
Private Sub drawFullChart(ByVal vpc As WinViewPortControl, ByVal viewer As WinChartViewer)
' Create an XYChart object of the same size as the Viewport Control
Dim c As XYChart = New XYChart(viewPortControl1.ClientSize.Width, viewPortControl1.ClientSize.Height)
' Set the plotarea to cover the entire chart. Disable grid lines by setting their colors
' to transparent. Set 4 quadrant coloring, where the colors of the quadrants alternate
' between lighter and deeper grey (dddddd/eeeeee).
c.setPlotArea(0, 0, c.getWidth() - 1, c.getHeight() - 1, -1, -1, &HFF0000, Chart.Transparent, _
Chart.Transparent).set4QBgColor(&HDDDDDD, &HEEEEEE, &HDDDDDD, &HEEEEEE, &H0)
' Set 4 quadrant mode, with both x and y axes symetrical around the origin
c.setAxisAtOrigin(Chart.XYAxisAtOrigin, Chart.XAxisSymmetric + Chart.YAxisSymmetric)
' The x and y axis scales reflect the full range of the view port
c.xAxis().setLinearScale(viewer.getValueAtViewPort("x", 0), viewer.getValueAtViewPort("x", 1), _
Chart.NoValue)
c.yAxis().setLinearScale(viewer.getValueAtViewPort("y", 0), viewer.getValueAtViewPort("y", 1), _
Chart.NoValue)
' Add scatter layer, using 3 pixels red (ff33333) X shape symbols
c.addScatterLayer(dataX0, dataY0, "Group A", Chart.Cross2Shape(), 3, &HFF3333, &HFF3333)
' Add scatter layer, using 3 pixels green (33ff33) circle symbols
c.addScatterLayer(dataX1, dataY1, "Group B", Chart.CircleShape, 3, &H33FF33, &H33FF33)
' Add scatter layer, using 3 pixels blue (3333ff) triangle symbols
c.addScatterLayer(dataX2, dataY2, "Group C", Chart.TriangleSymbol, 3, &H3333FF, &H3333FF)
' Set the chart image to the WinChartViewer
vpc.Chart = c
End Sub
'
' Update the image map
'
Private Sub updateImageMap(ByVal viewer As WinChartViewer)
' Include tool tip for the chart
If IsNothing(viewer.ImageMap) Then
viewer.ImageMap = viewer.Chart.getHTMLImageMap("clickable", "", _
"title='[{dataSetName}] Alpha = {x}, Beta = {value}'")
End If
End Sub
'
' ClickHotSpot event handler. In this demo, we just display the hot spot parameters in a pop up
' dialog.
'
Private Sub winChartViewer1_ClickHotSpot(ByVal sender As Object, ByVal e As WinHotSpotEventArgs) _
Handles winChartViewer1.ClickHotSpot
' We show the pop up dialog only when the mouse action is not in zoom-in or zoom-out mode.
If winChartViewer1.MouseUsage <> WinChartMouseUsage.ZoomIn And _
winChartViewer1.MouseUsage <> WinChartMouseUsage.ZoomOut Then
Dim f As New ParamViewer()
f.Display(sender, e)
End If
End Sub
'
' Pointer (Drag to Scroll) button event handler
'
Private Sub pointerPB_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs) _
Handles pointerPB.CheckedChanged
If sender.Checked Then
winChartViewer1.MouseUsage = WinChartMouseUsage.ScrollOnDrag
End If
End Sub
'
' Zoom In button event handler
'
Private Sub zoomInPB_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs) _
Handles zoomInPB.CheckedChanged
If sender.Checked Then
winChartViewer1.MouseUsage = WinChartMouseUsage.ZoomIn
End If
End Sub
'
' Zoom Out button event handler
'
Private Sub zoomOutPB_CheckedChanged(ByVal sender As Object, ByVal e As EventArgs) _
Handles zoomOutPB.CheckedChanged
If sender.Checked Then
winChartViewer1.MouseUsage = WinChartMouseUsage.ZoomOut
End If
End Sub
'
' Save button event handler
'
Private Sub savePB_Click(ByVal sender As Object, ByVal e As EventArgs) _
Handles savePB.Click
' The standard Save File dialog
Dim fileDlg As SaveFileDialog = New SaveFileDialog()
fileDlg.Filter = "PNG (*.png)|*.png|JPG (*.jpg)|*.jpg|GIF (*.gif)|*.gif|BMP (*.bmp)|*.bmp|" & _
"SVG (*.svg)|*.svg|PDF (*.pdf)|*.pdf"
fileDlg.FileName = "chartdirector_demo"
If fileDlg.ShowDialog() <> DialogResult.OK Then
Return
End If
' Save the chart
If Not IsNothing(winChartViewer1.Chart) Then
winChartViewer1.Chart.makeChart(fileDlg.FileName)
End If
End Sub
'
' ValueChanged event handler for zoomBar. Zoom in around the center point and try to
' maintain the aspect ratio
'
Private Sub zoomBar_ValueChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles zoomBar.ValueChanged
If Not winChartViewer1.IsInViewPortChangedEvent Then
'Remember the center point
Dim centerX As Double = winChartViewer1.ViewPortLeft + winChartViewer1.ViewPortWidth / 2
Dim centerY As Double = winChartViewer1.ViewPortTop + winChartViewer1.ViewPortHeight / 2
'Aspect ratio and zoom factor
Dim aspectRatio As Double = winChartViewer1.ViewPortWidth / winChartViewer1.ViewPortHeight
Dim zoomTo As Double = CDbl(zoomBar.Value) / zoomBar.Maximum
'Zoom while respecting the aspect ratio
winChartViewer1.ViewPortWidth = zoomTo * Math.Max(1, aspectRatio)
winChartViewer1.ViewPortHeight = zoomTo * Math.Max(1, 1 / aspectRatio)
'Adjust ViewPortLeft and ViewPortTop to keep center point unchanged
winChartViewer1.ViewPortLeft = centerX - winChartViewer1.ViewPortWidth / 2
winChartViewer1.ViewPortTop = centerY - winChartViewer1.ViewPortHeight / 2
'update the chart, but no need to update the image map yet, as the chart is still
'zooming and is unstable
winChartViewer1.updateViewPort(True, False)
End If
End Sub
'
' Draw track cursor when mouse is moving over plotarea
'
Private Sub winChartViewer1_MouseMovePlotArea(ByVal sender As Object, _
ByVal e As System.Windows.Forms.MouseEventArgs) Handles winChartViewer1.MouseMovePlotArea
Dim viewer As WinChartViewer = sender
crossHair(viewer.Chart, viewer.PlotAreaMouseX, viewer.PlotAreaMouseY)
viewer.updateDisplay()
' Hide the track cursor when the mouse leaves the plot area
viewer.removeDynamicLayer("MouseLeavePlotArea")
' Update image map if necessary. If the mouse is still dragging, the chart is still
' updating and not confirmed, so there is no need to set up the image map.
If Not viewer.IsMouseDragging Then
updateImageMap(viewer)
End If
End Sub
'
' Draw cross hair cursor with axis labels
'
Private Sub crossHair(ByVal c As XYChart, ByVal mouseX As Integer, ByVal mouseY As Integer)
' Clear the current dynamic layer and get the DrawArea object to draw on it.
Dim d As DrawArea = c.initDynamicLayer()
' The plot area object
Dim plotArea As PlotArea = c.getPlotArea()
' Draw a vertical line and a horizontal line as the cross hair
d.vline(plotArea.getTopY(), plotArea.getBottomY(), mouseX, d.dashLineColor(&H0, &H101))
d.hline(plotArea.getLeftX(), plotArea.getRightX(), mouseY, d.dashLineColor(&H0, &H101))
' Draw y-axis label
Dim label As String = "<*block,bgColor=FFFFDD,margin=3,edgeColor=000000*>" & c.formatValue( _
c.getYValue(mouseY, c.yAxis()), "{value|P4}") & "<*/*>"
Dim t As TTFText = d.text(label, "Arial Bold", 8)
t.draw(plotArea.getLeftX() - 5, mouseY, &H0, Chart.Right)
' Draw x-axis label
label = "<*block,bgColor=FFFFDD,margin=3,edgeColor=000000*>" & c.formatValue(c.getXValue(mouseX), _
"{value|P4}") & "<*/*>"
t = d.text(label, "Arial Bold", 8)
t.draw(mouseX, plotArea.getBottomY() + 5, &H0, Chart.Top)
End Sub
End Class
[WPF - XAML] NetWPFCharts\CSharpWPFCharts\XYZoomScrollWindow.xaml
<Window x:Class="CSharpWPFCharts.XYZoomScrollWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CSharpWPFCharts"
mc:Ignorable="d"
xmlns:ChartDirector="clr-namespace:ChartDirector;assembly=netchartdir" UseLayoutRounding="True"
Title="XY Zooming and Scrolling" Loaded="Window_Loaded" Background="#FFCCCCFF" SizeToContent="WidthAndHeight" ResizeMode="NoResize"
>
<DockPanel>
<Label Content="Advanced Software Engineering" Height="25" DockPanel.Dock="Top" FontFamily="Arial" FontStyle="Italic" FontWeight="Bold"
FontSize="13" Background="#FF02098D" Foreground="#FFF4FF04" HorizontalContentAlignment="Right"/>
<StackPanel DockPanel.Dock="Left" Width="120" Background="#FFF0F0F0">
<RadioButton x:Name="pointerPB" Style="{StaticResource {x:Type ToggleButton}}" HorizontalContentAlignment="Left" Checked="pointerPB_Checked" >
<StackPanel Orientation="Horizontal" Margin="5">
<Image Source="/icons/scroll_icon.png" Height="16" />
<TextBlock Text="Pointer" Margin="6,0,0,0" />
</StackPanel>
</RadioButton>
<RadioButton x:Name="zoomInPB" Style="{StaticResource {x:Type ToggleButton}}" HorizontalContentAlignment="Left" Checked="zoomInPB_Checked" >
<StackPanel Orientation="Horizontal" Margin="5" >
<Image Source="/icons/zoomin_icon.png" Height="16" />
<TextBlock Text="Zoom In" Margin="6,0,0,0" />
</StackPanel>
</RadioButton>
<RadioButton x:Name="zoomOutPB" Style="{StaticResource {x:Type ToggleButton}}" HorizontalContentAlignment="Left" Checked="zoomOutPB_Checked">
<StackPanel Orientation="Horizontal" Margin="5" >
<Image Source="/icons/zoomout_icon.png" Height="16" />
<TextBlock Text="Zoom Out" Margin="6,0,0,0" />
</StackPanel>
</RadioButton>
<Button x:Name="savePB" Margin="0,32,0,0" HorizontalContentAlignment="Left" Click="savePB_Click">
<StackPanel Orientation="Horizontal" Margin="5" >
<Image Source="/icons/save_icon.png" Height="16" />
<TextBlock Text="Save" Margin="6,0,0,0" />
</StackPanel>
</Button>
<TextBlock Text="Zoom Level" Margin="0,46,0,0" HorizontalAlignment="Center" FontWeight="Bold" />
<Slider x:Name="zoomBar" Margin="5" ValueChanged="zoomBar_ValueChanged" TickPlacement="Both" Foreground="#FF555555" />
<ChartDirector:WPFViewPortControl x:Name="ViewPortControl1" Width="110" Height="110" Margin="0,68,0,0"
ViewPortExternalColor="#7F000000" ViewPortBorderColor="#7FFFFFFF" SelectionBorderColor="#7FFFFFFF" />
</StackPanel>
<ChartDirector:WPFChartViewer x:Name="WPFChartViewer1" Width="500" Height="480" MouseMovePlotArea="WPFChartViewer1_MouseMovePlotArea"
ClickHotSpot="WPFChartViewer1_ClickHotSpot" ViewPortChanged="WPFChartViewer1_ViewPortChanged"
ScrollDirection="HorizontalVertical" ZoomDirection="HorizontalVertical" MouseWheelZoomRatio="1.1" />
</DockPanel>
</Window>
[WPF - C#] NetWPFCharts\CSharpWPFCharts\XYZoomScrollWindow.xaml.cs
using System;
using System.Windows;
using System.Windows.Input;
using Microsoft.Win32;
using ChartDirector;
namespace CSharpWPFCharts
{
/// <summary>
/// Interaction logic for XYZoomScroll.xaml
/// </summary>
public partial class XYZoomScrollWindow : Window
{
// XY data points for the chart
private double[] dataX0;
private double[] dataY0;
private double[] dataX1;
private double[] dataY1;
private double[] dataX2;
private double[] dataY2;
public XYZoomScrollWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// Connect the WPFViewPortControl to the WPfChartViewer
ViewPortControl1.Viewer = WPFChartViewer1;
// Load the data
loadData();
// Trigger the ViewPortChanged event to draw the chart
WPFChartViewer1.updateViewPort(true, true);
// Draw the full thumbnail chart for the ViewPortControl
drawFullChart(ViewPortControl1, WPFChartViewer1);
}
//
// Load the data
//
private void loadData()
{
//
// For simplicity, in this demo, we just use hard coded data.
//
dataX0 = new double[] { 10, 15, 6, -12, 14, -8, 13, -3, 16, 12, 10.5, -7, 3, -10, -5, 2, 5 };
dataY0 = new double[] {130, 150, 80, 110, -110, -105, -130, -15, -170, 125, 125, 60, 25, 150,
150, 15, 120};
dataX1 = new double[] { 6, 7, -4, 3.5, 7, 8, -9, -10, -12, 11, 8, -3, -2, 8, 4, -15, 15 };
dataY1 = new double[] {65, -40, -40, 45, -70, -80, 80, 10, -100, 105, 60, 50, 20, 170, -25, 50,
75};
dataX2 = new double[] { -10, -12, 11, 8, 6, 12, -4, 3.5, 7, 8, -9, 3, -13, 16, -7.5, -10, -15 };
dataY2 = new double[] {65, -80, -40, 45, -70, -80, 80, 90, -100, 105, 60, -75, -150, -40, 120,
-50, -30};
}
//
// The ViewPortChanged event handler. This event occurs if the user scrolls or zooms in
// or out the chart by dragging or clicking on the chart. It can also be triggered by
// calling WinChartViewer.updateViewPort.
//
private void WPFChartViewer1_ViewPortChanged(object sender, WPFViewPortEventArgs e)
{
var viewer = sender as WPFChartViewer;
// In addition to updating the chart, we may also need to update other controls that
// changes based on the view port.
updateControls(viewer);
// Update the chart if necessary
if (e.NeedUpdateChart)
drawChart(viewer);
// Update the image map if necessary
if (e.NeedUpdateImageMap)
updateImageMap(viewer);
}
//
// Update controls when the view port changed
//
private void updateControls(WPFChartViewer viewer)
{
// Synchronize the zoom bar value with the view port width/height
zoomBar.Value = Math.Min(viewer.ViewPortWidth, viewer.ViewPortHeight) * zoomBar.Maximum;
}
//
// Draw the chart and display it in the given viewer
//
private void drawChart(WPFChartViewer viewer)
{
// Create an XYChart object 500 x 480 pixels in size, with the same background color
// as the container
XYChart c = new XYChart(500, 480, 0xccccff);
// Set the plotarea at (50, 40) and of size 400 x 400 pixels. Use light grey (c0c0c0)
// horizontal and vertical grid lines. Set 4 quadrant coloring, where the colors of
// the quadrants alternate between lighter and deeper grey (dddddd/eeeeee).
c.setPlotArea(50, 40, 400, 400, -1, -1, -1, 0xc0c0c0, 0xc0c0c0
).set4QBgColor(0xdddddd, 0xeeeeee, 0xdddddd, 0xeeeeee, 0x000000);
// Enable clipping mode to clip the part of the data that is outside the plot area.
c.setClipping();
// Set 4 quadrant mode, with both x and y axes symetrical around the origin
c.setAxisAtOrigin(Chart.XYAxisAtOrigin, Chart.XAxisSymmetric + Chart.YAxisSymmetric);
// Add a legend box at (450, 40) (top right corner of the chart) with vertical layout
// and 8 pts Arial Bold font. Set the background color to semi-transparent grey.
LegendBox b = c.addLegend(450, 40, true, "Arial Bold", 8);
b.setAlignment(Chart.TopRight);
b.setBackground(0x40dddddd);
// Add a titles to axes
c.xAxis().setTitle("Alpha Index");
c.yAxis().setTitle("Beta Index");
// Set axes width to 2 pixels
c.xAxis().setWidth(2);
c.yAxis().setWidth(2);
// The default ChartDirector settings has a denser y-axis grid spacing and less-dense
// x-axis grid spacing. In this demo, we want the tick spacing to be symmetrical.
// We use around 50 pixels between major ticks and 25 pixels between minor ticks.
c.xAxis().setTickDensity(50, 25);
c.yAxis().setTickDensity(50, 25);
//
// In this example, we represent the data by scatter points. If you want to represent
// the data by somethings else (lines, bars, areas, floating boxes, etc), just modify
// the code below to use the layer type of your choice.
//
// Add scatter layer, using 11 pixels red (ff33333) X shape symbols
c.addScatterLayer(dataX0, dataY0, "Group A", Chart.Cross2Shape(), 11, 0xff3333);
// Add scatter layer, using 11 pixels green (33ff33) circle symbols
c.addScatterLayer(dataX1, dataY1, "Group B", Chart.CircleShape, 11, 0x33ff33);
// Add scatter layer, using 11 pixels blue (3333ff) triangle symbols
c.addScatterLayer(dataX2, dataY2, "Group C", Chart.TriangleSymbol, 11, 0x3333ff);
//
// In this example, we have not explicitly configured the full x and y range. In this case, the
// first time syncLinearAxisWithViewPort is called, ChartDirector will auto-scale the axis and
// assume the resulting range is the full range. In subsequent calls, ChartDirector will set the
// axis range based on the view port and the full range.
//
viewer.syncLinearAxisWithViewPort("x", c.xAxis());
viewer.syncLinearAxisWithViewPort("y", c.yAxis());
// We need to update the track line too. If the mouse is moving on the chart (eg. if
// the user drags the mouse on the chart to scroll it), the track line will be updated
// in the MouseMovePlotArea event. Otherwise, we need to update the track line here.
if ((!viewer.IsInMouseMoveEvent) && viewer.IsMouseOnPlotArea)
crossHair(c, viewer.PlotAreaMouseX, viewer.PlotAreaMouseY);
// Set the chart image to the ChartViewer
viewer.Chart = c;
}
//
// Draw the full thumbnail chart and display it in the given ViewPortControl
//
private void drawFullChart(WPFViewPortControl vpc, WPFChartViewer viewer)
{
// Create an XYChart object of the same size as the Viewport Control
XYChart c = new XYChart((int)vpc.ActualWidth, (int)vpc.ActualHeight);
// Set the plotarea to cover the entire chart. Disable grid lines by setting their colors
// to transparent. Set 4 quadrant coloring, where the colors of the quadrants alternate
// between lighter and deeper grey (dddddd/eeeeee).
c.setPlotArea(0, 0, c.getWidth() - 1, c.getHeight() - 1, -1, -1, 0xff0000, Chart.Transparent,
Chart.Transparent).set4QBgColor(0xdddddd, 0xeeeeee, 0xdddddd, 0xeeeeee, 0x000000);
// Set 4 quadrant mode, with both x and y axes symetrical around the origin
c.setAxisAtOrigin(Chart.XYAxisAtOrigin, Chart.XAxisSymmetric + Chart.YAxisSymmetric);
// The x and y axis scales reflect the full range of the view port
c.xAxis().setLinearScale(viewer.getValueAtViewPort("x", 0), viewer.getValueAtViewPort("x", 1),
Chart.NoValue);
c.yAxis().setLinearScale(viewer.getValueAtViewPort("y", 0), viewer.getValueAtViewPort("y", 1),
Chart.NoValue);
// Add scatter layer, using 3 pixels red (ff33333) X shape symbols
c.addScatterLayer(dataX0, dataY0, "Group A", Chart.Cross2Shape(), 3, 0xff3333, 0xff3333);
// Add scatter layer, using 3 pixels green (33ff33) circle symbols
c.addScatterLayer(dataX1, dataY1, "Group B", Chart.CircleShape, 3, 0x33ff33, 0x33ff33);
// Add scatter layer, using 3 pixels blue (3333ff) triangle symbols
c.addScatterLayer(dataX2, dataY2, "Group C", Chart.TriangleSymbol, 3, 0x3333ff, 0x3333ff);
// Set the chart image to the ViewPortControl
vpc.Chart = c;
}
//
// Update the image map
//
private void updateImageMap(WPFChartViewer viewer)
{
// Include tool tip for the chart
if ((viewer.ImageMap == null) && (viewer.Chart != null))
{
viewer.ImageMap = viewer.Chart.getHTMLImageMap("clickable", "",
"title='[{dataSetName}] Alpha = {x}, Beta = {value}'");
}
}
//
// ClickHotSpot event handler. In this demo, we just display the hot spot parameters in a pop up
// dialog.
//
private void WPFChartViewer1_ClickHotSpot(object sender, WPFHotSpotEventArgs e)
{
var viewer = sender as WPFChartViewer;
// We show the pop up dialog only when the mouse action is not in zoom-in or zoom-out mode.
if ((viewer.MouseUsage != WinChartMouseUsage.ZoomIn)
&& (viewer.MouseUsage != WinChartMouseUsage.ZoomOut))
new ParamViewer().Display(sender, e);
}
//
// Pointer (Drag to Scroll) button event handler
//
private void pointerPB_Checked(object sender, RoutedEventArgs e)
{
WPFChartViewer1.MouseUsage = WinChartMouseUsage.ScrollOnDrag;
}
//
// Zoom In button event handler
//
private void zoomInPB_Checked(object sender, RoutedEventArgs e)
{
WPFChartViewer1.MouseUsage = WinChartMouseUsage.ZoomIn;
}
//
// Zoom Out button event handler
//
private void zoomOutPB_Checked(object sender, RoutedEventArgs e)
{
WPFChartViewer1.MouseUsage = WinChartMouseUsage.ZoomOut;
}
//
// Save button event handler
//
private void savePB_Click(object sender, RoutedEventArgs e)
{
// The standard Save File dialog
SaveFileDialog fileDlg = new SaveFileDialog();
fileDlg.Filter = "PNG (*.png)|*.png|JPG (*.jpg)|*.jpg|GIF (*.gif)|*.gif|BMP (*.bmp)|*.bmp|" +
"SVG (*.svg)|*.svg|PDF (*.pdf)|*.pdf";
fileDlg.FileName = "chartdirector_demo";
var ret = fileDlg.ShowDialog(this);
if (!(ret.HasValue && ret.Value))
return;
// Save the chart
if (null != WPFChartViewer1.Chart)
WPFChartViewer1.Chart.makeChart(fileDlg.FileName);
}
//
// ValueChanged event handler for zoomBar. Zoom in around the center point and try to
// maintain the aspect ratio
//
private void zoomBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
var viewer = WPFChartViewer1;
if (!viewer.IsInViewPortChangedEvent)
{
//Remember the center point
double centerX = viewer.ViewPortLeft + viewer.ViewPortWidth / 2;
double centerY = viewer.ViewPortTop + viewer.ViewPortHeight / 2;
//Aspect ratio and zoom factor
double aspectRatio = viewer.ViewPortWidth / viewer.ViewPortHeight;
double zoomTo = ((double)zoomBar.Value) / zoomBar.Maximum;
zoomTo = Math.Max(zoomTo, Math.Min(viewer.ZoomInWidthLimit, viewer.ZoomInHeightLimit));
//Zoom while respecting the aspect ratio
viewer.ViewPortWidth = zoomTo * Math.Max(1, aspectRatio);
viewer.ViewPortHeight = zoomTo * Math.Max(1, 1 / aspectRatio);
//Adjust ViewPortLeft and ViewPortTop to keep center point unchanged
viewer.ViewPortLeft = centerX - viewer.ViewPortWidth / 2;
viewer.ViewPortTop = centerY - viewer.ViewPortHeight / 2;
//update the chart, but no need to update the image map yet, as the chart is still
//zooming and is unstable
viewer.updateViewPort(true, false);
}
}
//
// Draw track cursor when mouse is moving over plotarea, and update image map if necessary
//
private void WPFChartViewer1_MouseMovePlotArea(object sender, MouseEventArgs e)
{
var viewer = sender as WPFChartViewer;
// Draw crosshair track cursor
crossHair((XYChart)viewer.Chart, viewer.PlotAreaMouseX, viewer.PlotAreaMouseY);
viewer.updateDisplay();
// Hide the track cursor when the mouse leaves the plot area
viewer.removeDynamicLayer("MouseLeavePlotArea");
// Update image map if necessary. If the mouse is still dragging, the chart is still
// updating and not confirmed, so there is no need to set up the image map.
if (!viewer.IsMouseDragging)
updateImageMap(viewer);
}
//
// Draw cross hair cursor with axis labels
//
private void crossHair(XYChart c, int mouseX, int mouseY)
{
// Clear the current dynamic layer and get the DrawArea object to draw on it.
DrawArea d = c.initDynamicLayer();
// The plot area object
PlotArea plotArea = c.getPlotArea();
// Draw a vertical line and a horizontal line as the cross hair
d.vline(plotArea.getTopY(), plotArea.getBottomY(), mouseX, d.dashLineColor(0x000000, 0x0101));
d.hline(plotArea.getLeftX(), plotArea.getRightX(), mouseY, d.dashLineColor(0x000000, 0x0101));
// Draw y-axis label
string label = "<*block,bgColor=FFFFDD,margin=3,edgeColor=000000*>" + c.formatValue(c.getYValue(
mouseY, c.yAxis()), "{value|P4}") + "<*/*>";
TTFText t = d.text(label, "Arial Bold", 8);
t.draw(plotArea.getLeftX() - 5, mouseY, 0x000000, Chart.Right);
// Draw x-axis label
label = "<*block,bgColor=FFFFDD,margin=3,edgeColor=000000*>" + c.formatValue(c.getXValue(mouseX),
"{value|P4}") + "<*/*>";
t = d.text(label, "Arial Bold", 8);
t.draw(mouseX, plotArea.getBottomY() + 5, 0x000000, Chart.Top);
}
}
}
© 2023 Advanced Software Engineering Limited. All rights reserved.