基于GDI+的绘图控件开发
GDI+绘图控件的一些绘图函数包括绘制直线、曲线、圆弧、文本函数等,一些主要功能有缩放、移动和坐标变换(如图1所示)。绘制基本函数并不复杂,有一点GDI+基础就可以轻松编写这些函数,但是对于如何进行缩放和平移等操作,以及屏幕坐标(又称设备坐标)和绘图坐标(又称页面坐标)的变换则存在一定的难度和必须注意的事项。基本绘图函数在这里就不在讲解,下面主要讲述一下所用到的关键方法和注意事项。
绘图控件首先要解决的问题就是坐标的变换,在GDI+的坐标系统中坐标的类型有三种,即全局坐标、页面坐标和设备坐标。我们用鼠标点击获取的未经变换的坐标即为设备的坐标,而我们模型的绘制空间的坐标为全局坐标。我们要想当鼠标移动到绘图区域时,显示当前的绘图坐标(注意不应该是设备坐标),这个时候就需要进行坐标的变换了。而在GDI+中已经提供了这样的函数,在这里我们应注意,我们需要是把全局坐标转换到设备坐标的系统中,不要转错了哦!(1)坐标变换
实现方法:在控件里的picturebox控件的_MouseMove事件中添加如下代码即可,
points = newPointF[1];
points[0].X = (float)e.X;
points[0].Y = (float)e.Y;
graphics.TransformPoints(CoordinateSpace.World, CoordinateSpace.Device,points);
points[0].Y = -points[0].Y;
pointsText.Text = "x="+ points[0].X.ToString() + "," + "y=" + points[0].Y.ToString();
其中,graphics.TransformPoints()函数用于将坐标的变换。如图1的左下角所示。但是我们通常所用的坐标原点一般在左下角,而系统的默认坐标却在左上角,因此还需要进行原点坐标的平移变换(将在下面讲解)。
(2)缩放和平移
大家都知道在GDI+中为我们提供了图形的缩放(ScaleTransform())和平移(TranslateTransform())的函数。他们要求图形的绘制必须和缩放、平移在同函数下进行绘制。
因此,我们简单的在控件中简单的写几个绘制图形的函数,然后在控件以外调用这个函数,是不能实现图形的缩放和平移操作的。
所以,我们需要在控件中给各个图形定义一个结构或类来存储图形的属性信息,然后在每次绘制的过程中,用一个动态数组存储对应的图形信息即可,如下绘制直线的定义方法:
首先定义直线类,
public class LineObject
{
public double StartX;
public double StartY;
public double EndX;
public double EndY;
public Color Color;
public float LineWidth;
}
然后,定义绘制直线的函数,
/// <summary>
/// 绘制直线
/// </summary>
/// <paramname="color">直线颜色</param>
/// <paramname="width">直线宽度</param>
/// <paramname="x1">第一个点x值</param>
/// <paramname="y1">第一个点y值</param>
/// <paramname="x2">第二个点x值</param>
/// <paramname="y2">第二个点y值</param>
public void DrawLine( Colorcolor,double width,doublex1, double y1,doublex2,double y2)
{
LineObjecttempLine = new LineObject();
tempLine.Color = color;
tempLine.LineWidth =(float) width;
tempLine.StartY = x1;
tempLine.StartY = y1;
tempLine.EndX = x2;
tempLine.EndY = y2;
LinesArray.Add(tempLine);
Render();
}
最后,在render()函数中添加绘制直线的代码和图形缩放代码如下
graphics.ScaleTransform(scaleFactor,scaleFactor);//缩放
graphics.TranslateTransform(originXY.X,originXY.Y);//移动
//绘制直线
if (LinesArray.Count > 0)
{
PenlinePen;
foreach (LineObject tempLine inLinesArray)
{
linePen = newPen(tempLine.Color, tempLine.LineWidth);
graphics.DrawLine(linePen, (float)tempLine.StartX,
- (float)tempLine.StartY,(float)tempLine.EndX , - (float)tempLine.EndY);
}
}
外部进行绘图的时候,直接调用DrawLine()即可,通过这种方式定义不仅方便进行缩放和平移,更方便图形的输出。
(3)坐标原点设置
坐标原点的设置在知道缩放和平移的原理后,坐标原点的设置就比较简单了。坐标原点的设置可以理解为把坐标原点从左上角移动到一个我们想要的位置(本文移动到左下角(10,10))的位置,通过平移函数即可,但是我们应注意平移函数要放在缩放函数的前面,不然当缩放的时候缩放点还是以左上角进行缩放,同样还要注意假如y轴的方向翻转时(例如本控件中y向上)在写各个图形的代码时,y值要进行相应的改为负值。
在render函数中添加如下代码即可,
graphics.TranslateTransform(OpointF.X,OpointF.Y);
(4)平移时闪动问题
本文是总结自己在写控件过程中遇到的一些问题,仅此帮助那些像自己不懂的童鞋们学习和参考。因为书写比较仓促和限于本人水平有限,错误之处恳请指出。