虽然是c++的,但总有一些相通的地方。
窗口刷新的时候,会产生paint事件,那么我们给这个事件添加一个处理函数。然后在这个函数里画图。就能保证所画的图不被刷新掉,
它可以总是显示。paint事件对应的委托是:public delegate void painteventhandler(object sender, painteventargs e);
先来个最简单的绘制,在窗口上画一根线。(创建windowsforms应用程序)
public partial class form1 : form
{
public form1()
{
initializecomponent();
//添加paint事件处理函数
this.paint += formpaint;
}
private void formpaint(object sender, painteventargs e)
{
graphics graphics = e.graphics;
//画笔,绿色,2像素宽
pen pen=new pen(color.fromargb(0,255,0),2);
//画一根线,两点是0,0和100,100
graphics.drawline(pen,new point(0,0),new point(100,100));
}
}
像绘制直线,矩形,圆形,还有图片,都可以通过graphics类来完成。
示例2:一个填充矩形
graphics graphics = e.graphics;
//蓝色画刷
solidbrush brush = new solidbrush(color.fromargb(0, 0, 255));
//一个矩形
rectangle rect = new rectangle(0, 0, 100, 100);
//填充一个矩形
graphics.fillrectangle(brush, rect);
示例3:画一张png图片(用png是因为可以显示透明的图片,gif图片也有这个作用)
private void formpaint(object sender, painteventargs e)
{
graphics graphics = e.graphics;
//加载图片
image img=image.fromfile(d:\\image\\win.png);
//图片显示起始位置
point strpoint=new point(50,50);
//不限制大小绘制
graphics.drawimage(img, strpoint);
//缩小图片绘制,限制在一个矩形内
rectangle rect=new rectangle(50,50,100,100);
graphics.drawimage(img, rect);
}
用drawstring显示文字
drawstring在grahpics类里有好几个重载,有的可以让字符串在一个矩形内显示,有的可以使用特定的显示格式。这里就不做详细介绍了。
只讲比较常用的。
看例子吧,处理键盘输入字符事件,在窗口显示输入的字符。如下:
public partial class form1 : form
{
public static string strtext = ;
public form1()
{
initializecomponent();
this.paint += formpaint;
this.keypress += formkeypress;
}
private void formpaint(object sender, painteventargs e)
{
graphics graphics = e.graphics;
//创建画刷
solidbrush brush=new solidbrush(color.fromargb(0,255,0));
//创建字体
font font=new font(宋体,20f);
//显示字符串,在一个矩形内
graphics.drawstring(strtext, font, brush, this.clientrectangle);
}
private void formkeypress(object sender, keypresseventargs e)
{
strtext += e.keychar;
//刷新整个窗口
this.invalidate();
}
}
还有graphics.drawstring(strtext, font, brush, new point(100, 100));显示方式,这个只是指定了文字显示的起始位置。
关于显示格式看下例:
//显示字符串,在一个矩形内
stringformat strformat = new stringformat(stringformatflags.directionrighttoleft);
graphics.drawstring(strtext, font, brush, this.clientrectangle,strformat);
stringformatflags是一个枚举类型,自己一个一个试吧,看看每个枚举成员表示什么样的格式。
接下来,我们来看一下。form类中默认处理事件的方法,和你的添加的事件处理方法,这两者有什么关系。
一个示例:处理鼠标左键事件
public partial class form1 : form
{
private color prbackcolor;
public form1()
{
initializecomponent();
//窗口默认的背景颜色
prbackcolor = this.backcolor;
//添加事件处理
this.mousedown += formmousedown;
this.mouseup += formmouseup;
}
//鼠标键按下事件处理方法
private void formmousedown(object sender, mouseeventargs e)
{
//如果是鼠标右键按下
if (e.button == mousebuttons.right)
{
form1 form1 = (form1)sender;
//改变背景颜色
form1.backcolor = color.fromargb(0, 255, 0);
}
}
//鼠标键弹起(松开)事件处理方法
private void formmouseup(object sender, mouseeventargs e)
{
if(e.button==mousebuttons.right)
{
form1 form1 = (form1)sender;
form1.backcolor = prbackcolor;
}
}
}
像鼠标键按下mousedown和鼠标键松开,form都有默认的事件处理方法,这些方法都是虚方法,你可以重写它们,比如重写
protected virtual void onmousedown(mouseeventargs e);和protected virtual void onmouseup(mouseeventargs e);
这样就可以不必添加事件处理方法,也能处理鼠标事件了,可以通过重写父类默认事件处理方法,来实现上面的例子。
而在查msdn可以发现,像这些默认的事件处理方法,调用都能引发其对应的事件。比如,我调用了onmousedown就能引发鼠标左键按下事件,其实也就是执行了我们添加的事件处理方法(委托)。而且我们还是多播委托的,因为我们是用+=添加委托方法的。
这样的话,如果你重写了onmousedown一定要在里面调用基类的onmousedown方法,
不然我们添加的mousedown方法就不会被执行(如果有)
那么知道了上面那些,我就来做一个实际例子吧。重写onpaintbackground绘制背景的方法。
public partial class form1 : form
{
public form1()
{
initializecomponent();
}
//重写onpaintbackground方法
protected override void onpaintbackground(painteventargs e)
{
//禁止基类处理,我们自己来绘制背景
//base.onpaintbackground(e);
//透明背景画刷
solidbrush brush=new solidbrush(color.transparent);
//填充整个窗口
e.graphics.fillrectangle(brush,this.clientrectangle);
//再画一个圆圈
pen pen = new pen(color.fromargb(0, 255, 0),3);
e.graphics.drawellipse(pen, this.clientrectangle);
}
}
texturebursh图片画刷
可以用图片来填充一个形状,如矩形,圆形。图片不够大则平铺显示。
示例:
private void formpaint(object sender, painteventargs e)
{
graphics graphics = e.graphics;
//创建图片画刷
rectangle rect = new rectangle(10, 10, 70, 70);
texturebrush brush = new texturebrush(image.fromfile(d:\\image\\345.jpg),rect);
graphics.fillellipse(brush, 0, 0, 200, 200);
}
构造函数最后一个参数,rect表示要用图片的哪部分进行填充,10,10表示图片起始位置(左上角),70,70表示宽度和高度,注意不能超出图片原有范围。整张图片填充的话,则不需要指定rect。构造函数里填一个参数就行了。
lineargradientbursh线性渐变画刷(这个类存在于system.drawing.drawing2d命名空间里)
lineargradientbursh类有一个构造函数重载,它有四个参数,是两个点,和两种颜色。
这四个参数指定了起始点的颜色,和结束点的颜色。还有位置。
看下例:
public partial class form1 : form
{
public form1()
{
initializecomponent();
this.paint += formpaint;
}
private void formpaint(object sender, painteventargs e)
{
graphics graphics = e.graphics;
lineargradientbrush linebrush = new lineargradientbrush(new point(0, 0), new point(50, 0),
color.fromargb(255, 255, 255), color.fromargb(0, 0, 0));
//填充整个窗口
graphics.fillrectangle(linebrush,this.clientrectangle);
}
}
起始点是0,0 结束点是0,50的效果图。从白色到黑色的渐变颜色段。超过50的部分,又开始重新渐变。
就好比在使用ps的时候,渐变颜色是白到黑,然后拉一根线。起始点是0,0,结束点是0,50。
那么如果我用这个属性的渐变画刷在窗口随便画一个矩形是什么样的呢,看上面效果图就可以知道。
比如 graphics.fillrectangle(linebrush, 0, 0, 100, 100);
这个矩形的画刷填充跟第一张效果的对应的矩形区域是一样的。
如果改变起始点和结束点的值,也可以看得出来。这其中是按着什么方式来填充的。
比如起始点改成0,0,结束点改变50,50。
private void formpaint(object sender, painteventargs e)
{
graphics graphics = e.graphics;
lineargradientbrush linebrush = new lineargradientbrush(new point(0, 0), new point(50, 50),
color.fromargb(255, 255, 255), color.fromargb(0, 0, 0));
//填充整个窗口
graphics.fillrectangle(linebrush, this.clientrectangle);
pen pen = new pen(color.fromargb(0, 255,0));
graphics.drawrectangle(pen, 0, 0, 50, 50);
}
在里面绘制填充图形,就是按上面的规则来显示的。这个窗口并没有禁止掉最大化功能,可以改变窗口大小以便更进一步的观察。
多种颜色渐变
lineargradientbrush类有个interpolationcolors属性成员可以指定多种颜色渐变,这个成员是一个colorblend类型,像之前的渐变,都只能限于两种颜色的渐变,使用了interpolationcolors后,就可以使用多种,如从红到绿的渐变,然后绿到蓝。
看示例:
private void formpaint(object sender, painteventargs e)
{
//创建colorblend对象,指定多种颜色渐变信息
colorblend color_blend=new colorblend();
//指定几种颜色
color_blend.colors=new color[]{color.red,color.green,color.blue};
//指定颜色的范围
color_blend.positions=new float[]{0/3f,2/3f,3/3f};
rectangle rect=new rectangle(0,0,200,100);
//创建渐变画刷
lineargradientbrush brush=
new lineargradientbrush(new point(0,0),new point(200,0),color.white,color.white);
brush.interpolationcolors=color_blend;
e.graphics.fillrectangle(brush,rect);
}
color_blend.colors数组是指定有多少颜色渐变,比如上面就是红绿蓝,那么渐变应该是这样的,从红到绿渐变,然后从绿到蓝渐变。
color_blend.positions指定颜色的范围,如把那上面那个矩形宽度看作整体1的话,那么红到绿渐变,是从0/3f至2/3f完成的,也就是在这个
范围内完成了红到绿的渐变,那么绿到蓝渐变的范围就是2/3f至3/3f。
如果要各占一半的话,那就是color_blend.positions=new float[]{0/2f,1/2f,2/2f};
更多c# gdi+编程(一)。