谈到画图,少不了这几样东西,画图的人(咱们暂且说是画家),画笔,还有根据具体图形需要的各种参数,例如直线需要的是两个点的坐标等等。
谈到GDI+绘图,首先想到的最重要的就是Graphics类了,首先我们需要创建一个绘图类的实例Graphics g = this.CreateGraphics();//画家
在这里为啥不是 Graphics a = new Graphics();
呢?
如图可以看出编译器提示不包含0个参数的构造函数,这是怎么回事呢?我们都知道Graphics是一个类,当我们创造一个新的类时,我们都要为其编写构造函数,大多数构造函数都是空的,因此当我们不写构造函数时,编译器会自动生成一个空的构造函数以供使用,同时Graphics也是如此,但是一个空的构造函数Graphics又是不承认的,因此此处我们可以这样写Graphics g = this.CreateGraphics();
this 代表当前这个窗体,用当前这个窗体来创建Graphics的实例。
首先我们先从最简单的直线开始做起,我们先创建一个直线,如图所示
Graphics g = this.CreateGraphics();//画家 Pen p = new Pen(Brushes.Green,66);//画笔 Point p1 = new Point(30, 50);//两点 Point p2 = new Point(250, 250); g.DrawLine(p, p1, p2);
由图中所示
Pen p = new Pen(Brushes.Green,66);//画笔
创造了画笔的实例,其中包含两个参数,前一个是画笔的颜色,这个是必须要有的,后一个“66”是画笔的粗细,可以不写,不写的话系统自动默认一个画笔宽度(如图所示66就这么宽)
Point p1 = new Point(30, 50);//两点
Point p2 = new Point(250, 250);
其次Point创建了两个坐标的实例,这个应该非常好理解,最后就是最关键的一步了g.DrawLine(p, p1, p2);
将画笔两个坐标填到绘图类的实例当中,一个直线就应而生了。
其次我们循序渐进,来画一个矩形,如下所示
Graphics g = this.CreateGraphics();//画家 Pen p = new Pen(Brushes.Green,33);//画笔 Size size = new System.Drawing.Size(298,299);//矩形的像素(相当于矩形的长和宽) Rectangle rec = new Rectangle(new Point(120,150),size); g.DrawRectangle(p, rec);
这个比刚才多了一个Size实例,多了一个Rectangle实例,其中size代表像素,暂且我们可以理解为这个矩形的长和宽,还有就是Rectangle矩形类,要创建一个矩形,我们要知道这个矩形的位置和矩形的大小,因此其中的两个参数如图所示,最后我们g.DrawRectangle(p, rec);
,一个矩形就做成了。
然后我们循序渐进做一个扇形
Graphics p = this.CreateGraphics(); Pen p1 = new Pen(Brushes.Aquamarine,13); Size s = new Size(150, 150); Rectangle rec = new Rectangle(new Point(120, 150), s); p.DrawPie(p1, rec, 75, 105);//扇形
这里比较奇怪的是画扇形为何用到了一个矩形类,这里我也不太清楚哈哈哈哈!其中Size的两个参数我们可以当作扇形两条直角边的长度,而Point的坐标是图形左上角的坐标。最后那两个75,105代表两个角度如上图所示;我们再试着在这个上行下面加一个文字试试,如下所示
` p.DrawString(“生日快乐”, new Font(“楷体”, 20, FontStyle.Strikeout), Brushes.Red, new Point(300, 300));其中详细的参数介绍参考代码下面的汉字注解。
下面终于到我们的验证码正菜了,大体代码如下
Random r = new Random();
tring str = null;
for(int i = 0; i < 5; i++)
{
int s= r.Next(0, 10);
str += s;
}
Bitmap bmp = new Bitmap(66,33);
Graphics g = Graphics.FromImage(bmp);
string[] font = { "微软雅黑", "宋体", "黑体", "隶书" ,"仿宋","楷书"};
Color[] colors = { Color.Yellow, Color.Black, Color.Blue, Color.Red,Color.DarkSlateBlue,Color.DarkRed,Color.GreenYellow,Color.HotPink };
FontStyle[] style = { FontStyle.Bold, FontStyle.Underline, FontStyle.Italic, FontStyle.Strikeout ,FontStyle.Regular};
for (int i = 0; i < 5; i++)
{
Point p = new Point(i * 10 + 10, 11);
g.DrawString(str[i].ToString(), new Font(font[r.Next(0, 6)], r.Next(15,20), style[r.Next(0,5)]), new SolidBrush(colors[r.Next(0, 8)]), p);
}
for(int i = 0; i < 9; i++)
{
Point p = new Point(r.Next(0, bmp.Width), r.Next(0, bmp.Height));
Point p1 = new Point(r.Next(0, bmp.Width), r.Next(0, bmp.Height));
g.DrawLine(new Pen(colors[r.Next(0, 8)]), p, p1);
}
for(int i = 0; i < 66; i++)
{
Point p2 = new Point(r.Next(0, bmp.Width), r.Next(0, bmp.Height));
bmp.SetPixel(p2.X, p2.Y, colors[r.Next(0, 8)]);
}
pictureBox1.Image = bmp;`
效果如下,点击更换
首先第一步
Random r = new Random(); tring str = null; for(int i = 0; i < 5; i++) { int s= r.Next(0, 10); str += s; }
构造一个随机的五位数字的字符串用作验证码,然后:
Bitmap bmp = new Bitmap(66,33); Graphics g = Graphics.FromImage(bmp); string[] font = { "微软雅黑", "宋体", "黑体", "隶书" ,"仿宋","楷书"}; Color[] colors = { Color.Yellow, Color.Black, Color.Blue, Color.Red,Color.DarkSlateBlue,Color.DarkRed,Color.GreenYellow,Color.HotPink }; FontStyle[] style = { FontStyle.Bold, FontStyle.Underline, FontStyle.Italic, FontStyle.Strikeout ,FontStyle.Regular};
其中Bitmap是一种照片格式,名叫位图,因为验证码就以由一个照片展示的 。如图构造为一个width为66像素,Heigh为33像素的位图。然后老一套创建一个Graphics的实例,不同的是把this.CreateGraphics();
改为Graphics.FromImage(bmp);
,原因是:我们都知道验证码我们要照顾到所有人群,难免有些验证码会看不清,这时就要点击进行更换,如果还是this的话就是根据这个窗体对象创建的,当我们点击刷新时原来的验证码不会被抹去,验证码就越积越多导致无法查看,因此就无法更换了。Graphics.FromImage(bmp);表示是一个专门表示图片的类,其中的参数是一个image。我们给他一个Bitmap类的实例bmp(Bitmap是Image的子类)。
然后创建一个字符串数组,内容为为字体(越多越好,在此我只是实例一番)。同样的的也创建一个Color类的数组,一个FontStyle类的数组(FontStyle表示字体样式)。然后:
for (int i = 0; i < 5; i++)
{
Point p = new Point(i * 10 + 10, 11);
g.DrawString(str[i].ToString(), new Font(font[r.Next(0, 6)], r.Next(15, 20), style[r.Next(0, 5)]), new SolidBrush(colors[r.Next(0, 8)]), p);
}
for (int i = 0; i < 9; i++)
{
Point p = new Point(r.Next(0, bmp.Width), r.Next(0, bmp.Height));
Point p1 = new Point(r.Next(0, bmp.Width), r.Next(0, bmp.Height));
g.DrawLine(new Pen(colors[r.Next(0, 8)]), p, p1);
}
for (int i = 0; i < 66; i++)
{
Point p2 = new Point(r.Next(0, bmp.Width), r.Next(0, bmp.Height));
bmp.SetPixel(p2.X, p2.Y, colors[r.Next(0, 8)]);
}
第一个for是通过DrawString写数字,字体的样式颜色大小等等,都用到我们前面构造的对应的数组,参数用到了随机数更保证了安全性(Color那里不用数组的原因是Color不能重载在那个地方,因此我们调用SolidBrush(笔刷)能起到添加颜色的作用更重要的是其参数就是一个Color)【这里的g.DrawString里面的p坐标是以位图左上角为(0,0)点来进行定位的】,其次第二个for是用来画线的来保证验证码一定的模糊性,值得注意的是线段不要画到验证码图片范围之外,就
Bitmap bmp = new Bitmap(66, 33); Graphics g = Graphics.FromImage(bmp);
然后第三个for用来点上66个像素点,更增加了其模糊感,这个我们直接再bmp上调用SetPixe(像素点),同样不要点到验证码图片之外。最后:pictureBox1.Image = bmp;
我们把构造成功的bmp填到照片盒子这个空间中就大功告成了。