使用devexpress 控件能够做出美观漂亮的界面,其丰富的控件库大多能够满足我们日常开发的要求。但在有的方面DEVexpress还是做得不够完善的,比如说其图表控件(charting)库就不支持局部缩放功能,而dev默认提供的缩放功能实在是太差劲了,怎么办呢,一个图表的缩放是其亮点之一,又不能没有。怎么才能实现想要的局部缩放功能呢?
我现在想要的效果是选定图表的局部区域,对选定的局部区域放大,同时又要保留初始的图表使放大后的图能够还原到初始状态。在此将操作分为两个功能,一是局部放大,二是还原。实现局部放大效果的操作分解为以下三个触发事件,先后顺序是:左键点击图表、向右下拖动鼠标移动、释放左键。还原操作分解为两个触发事件,先后顺序是:左键点击图表,除右下方向外的其它方向脱东鼠标移动、释放左键。这里要判断光标是否有移动,没有位移移动就不是以上的局部放大和还原操作。实现代码如下
//======================================================================
//
// Copyright (C)
// All rights reserved
//
// created by 王超 at 10/12/2014
// email:atasas@163.com
//
//======================================================================
private bool _isScale = false;//鼠标左键是否按下
private object _maxX, _minX, _maxY, _minY,_maxX1, _minX1, _maxY1, _minY1;//原图X轴和Y轴的最大和最小值以及第二坐标轴(如果有)X轴和Y轴的最大和最小值
private object _x0, _x1, _y0, _y1;
private object _x00, _y00, _x11,_y11;
private Point _p0 = new Point();
private Point _p1 = new Point();
//单击左键
void DevUCChart_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_p0 = e.Location;
SetLocationClientValue(_p0, ref _x0, ref _y0,ref _x00,ref _y00);
_isScale = true;
}
}
//将屏幕坐标转换为图表的坐标
void SetLocationClientValue(Point p,ref object x0,ref object y0,ref object x1,ref object y1)
{
try
{
XYDiagram diagram = this.Diagram as XYDiagram;
DiagramCoordinates coord = diagram.PointToDiagram(p);
switch (coord.ArgumentScaleType)
{
case ScaleType.DateTime:
x0 = coord.DateTimeArgument;
break;
case ScaleType.Numerical:
x0 = coord.NumericalArgument;
break;
case ScaleType.Qualitative:
x0 = coord.QualitativeArgument;
break;
}
switch (coord.ValueScaleType)
{
case ScaleType.DateTime:
y0 = coord.DateTimeValue;
break;
case ScaleType.Numerical:
y0 = coord.NumericalValue;
break;
}
if (diagram.GetAllAxesX().Count > 1)
{
AxisValue ax = coord.GetAxisValue(diagram.GetAllAxesX()[1]);
switch (coord.ArgumentScaleType)
{
case ScaleType.DateTime:
x1 = ax.DateTimeValue;
break;
case ScaleType.Numerical:
x1 = ax.NumericalValue;
break;
case ScaleType.Qualitative:
x1 = ax.QualitativeValue;
break;
}
}
if (diagram.GetAllAxesY().Count > 1)
{
AxisValue ax = coord.GetAxisValue(diagram.GetAllAxesY()[1]);
switch (coord.ValueScaleType)
{
case ScaleType.DateTime:
y1 = ax.DateTimeValue;
break;
case ScaleType.Numerical:
y1 = ax.NumericalValue;
break;
}
}
}
catch
{
}
}
//拖动鼠标事件,绘制虚线矩形
void DevUCChart_MouseMove(object sender, MouseEventArgs e)
{
if (_isScale)
{
Point pE = new Point(e.Location.X - this.Location.X, e.Location.Y - this.Location.Y);
Graphics g = this.CreateGraphics();
Pen pen = new Pen(new SolidBrush(Color.FromArgb(100, 100, 100)));
pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
g.DrawRectangle(pen, _p0.X, _p0.Y, e.Location.X - _p0.X, e.Location.Y - _p0.Y);
}
}
//释放左键事件
void DevUCChart_MouseUp(object sender, MouseEventArgs e)
{
try
{
if (e.Button == MouseButtons.Left)
{
_p1 = e.Location;
SetLocationClientValue(_p1, ref _x1, ref _y1, ref _x11, ref _y11);
XYDiagram diag = (XYDiagram)this.Diagram;
if (_p1.X ==_p0.X && _p1.Y == _p0.Y)//没有拖动操作
{
return;
}
if (_p1.X > _p0.X && _p1.Y > _p0.Y)//右下拖动,局部方大
{
diag.AxisX.Range.MaxValue = _x1;
diag.AxisX.Range.MinValue = _x0;
if (diag.AxisY.Range.MinValue is double)
{
double __y1 = (double)_y1;
double __y0 = (double)_y0;
diag.AxisY.Range.MaxValue = __y1 > __y0 ? __y1 : __y0;
diag.AxisY.Range.MinValue = __y1 > __y0 ? __y0 : __y1;
}
if (diag.GetAllAxesX().Count > 1)
{
diag.GetAllAxesX()[1].Range.MinValue = _x00;
diag.GetAllAxesX()[1].Range.MaxValue = _x11;
}
}
else//其它方向拖动,还原
{
diag.AxisX.Range.MinValue = _minX;
diag.AxisX.Range.MaxValue = _maxX;
diag.AxisY.Range.MinValue = _minY;
diag.AxisY.Range.MaxValue = _maxY;
if (diag.GetAllAxesX().Count > 1)
{
diag.GetAllAxesX()[1].Range.MinValue = _minX1;
diag.GetAllAxesX()[1].Range.MaxValue = _maxX1;
}
else
{
diag.GetAllAxesY()[1].Range.MinValue = _minY1;
diag.GetAllAxesY()[1].Range.MaxValue = _maxY1;
}
}
}
}
catch
{ }
finally {
_isScale = false;
}
}
效果如下:
1、选定区间x轴: 2月8号到3月14号,y轴:1.4到2.5
2、局部方大效果
以上就是我实现的对devexpress控件库图表控件的局部缩放扩展功能,虽然还是有点不完美,但基本上能满足我的要了。