*本文大部分都参考了MSDN的文章,非原创
在创建自行绘制的控件时,应从 System.Windows.Forms.Control 中派生,并覆盖 OnPaint 和 OnPaintBackground 事件。 下面是一个最简单的例子:
当然,现在这个ImageButton除了能显示一张图片以外什么也不能做,我将在后面一步一步完善它。
OnPaint 事件的特性是它可以根据操作系统的要求无限次调用。在实例化和销毁这些对象上浪费时间将会影响绘图性能。 出现所谓的“闪烁”现象,通常采用“双缓冲”来减小这一因素的影响:
private Bitmap imageBuffer;

protected override void OnPaint(PaintEventArgs e)
{
Graphics gBuffer; //屏幕外的图像
Rectangle imageRect; //图像矩形

//在内存中绘制位图
if (imageBuffer == null)
{
imageBuffer = new Bitmap(ClientSize.Width, ClientSize.Height);
}

imageRect = this.ClientRectangle;
gBuffer = Graphics.FromImage(imageBuffer);

gBuffer.Clear(this.BackColor); //清除绘图面并以背景色填充
gBuffer.DrawImage(this.Image, 0, 0, imageRect, GraphicsUnit.Pixel);

//从内存位图绘制
e.Graphics.DrawImage(imageBuffer, 0, 0);

base.OnPaint(e);
}
在上面的代码中,我们通过调用 Graphics 类的静态 FromImage 方法在与我们的控件大小相同的空位图中创建了一个 Graphics 对象。我们在内存中的 Graphics 对象上进行所有的绘图,完成后,将整个准备好的位图覆盖到控件的图形上即可。源代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Animation
{
public partial class ImageButton : Control
{
private Image image;
private bool bePushsd;
private Bitmap imageBuffer;

public ImageButton()
{
this.Size = new Size(100, 100);
bePushsd = false;
}

public Image Image
{
get { return this.image; }
set { this.image = value; }
}

protected override void OnPaint(PaintEventArgs e)
{
Graphics gBuffer;
Rectangle imageRect; //图像矩形
Brush backBrush;

//在内存中绘制位图
if (imageBuffer == null)
{
imageBuffer = new Bitmap(ClientSize.Width, ClientSize.Height);
}

gBuffer = Graphics.FromImage(imageBuffer);

gBuffer.Clear(this.BackColor); //清除绘图面并以背景色填充

if (!bePushsd)
{
backBrush = new SolidBrush(Parent.BackColor);
}
else
{
backBrush = new SolidBrush(Color.LightGray);
}

gBuffer.FillRectangle(backBrush, this.ClientRectangle);

if (this.Image != null)
{
int imageLeft = (this.Width - this.Image.Width) / 2;
int imageTop = (this.Height - this.Image.Height) / 2;

if (!bePushsd)

{
imageRect = new Rectangle(imageLeft, imageTop, this.Image.Width, this.Image.Height);
}
else

{
imageRect = new Rectangle(imageLeft + 2, imageTop + 2, this.Image.Width, this.Image.Height);
}

gBuffer.DrawImage(this.Image, imageRect, 0, 0, this.Image.Width, this.Image.Height, GraphicsUnit.Pixel);
}


//从内存位图绘制
e.Graphics.DrawImage(imageBuffer, 0, 0);

base.OnPaint(e);
}

protected override void OnPaintBackground(PaintEventArgs pevent)
{
base.OnPaintBackground(pevent);
}

protected override void OnMouseDown(MouseEventArgs e)
{
bePushsd = true;
this.Invalidate();
}

protected override void OnMouseUp(MouseEventArgs e)
{
bePushsd = false;
this.Invalidate();
}
}
}
然而,陈现在控件上的一张图片,我们如何让其显示透明图像,为了使图像透明,我们使用下面这个函数来获取图片的背景颜色:
private Color ImageBackColor(Image image)
{
return (new Bitmap(image)).GetPixel(0, 0);
}
然后使用ImageAttributes类的public void SetColorKey(Color colorLow, Color colorHigh) 方法设置透明键值,此方法设置高低颜色键值,以便颜色范围可以成为透明的。对于任何颜色,只要它的三种颜色成分(红、绿、蓝)都处于高低颜色键的对应成分之间,它的颜色就会成为透明的。在使用该类首先要添加如下命名空间:
using System.Drawing.Imaging;
要使用该方法,将上面的红颜色代码改为如下即可:
这只是一个示例,还有很多不足之处,读者可以自己对其进行扩展,如加入Attributes的支持、为图片在控件中的陈现提供不同的方式(如当图片大于控件的尺寸时,是否对图片进行缩放)等。
http://www.cnblogs.com/nihgwu/archive/2006/07/17/452979.html
在创建自行绘制的控件时,应从 System.Windows.Forms.Control 中派生,并覆盖 OnPaint 和 OnPaintBackground 事件。 下面是一个最简单的例子:
1
using System;
2
using System.Collections.Generic;
3
using System.ComponentModel;
4
using System.Data;
5
using System.Drawing;
6
using System.Text;
7
using System.Windows.Forms;
8
9
namespace Animation
10
{
11
public partial class ImageButton : Control
12
{
13
private Image image;
14
15
public ImageButton()
16
{
17
InitializeComponent();
18
}
19
20
public Image Image
21
{
22
get { return this.image; }
23
set { this.image = value; }
24
}
25
26
protected override void OnPaint(PaintEventArgs pe)
27
{
28
if (image != null)
29
{
30
Graphics g = pe.Graphics;
31
g.DrawImage(image, this.ClientRectangle);
32
}
33
34
// 调用基类 OnPaint
35
base.OnPaint(pe);
36
}
37
38
protected override void OnPaintBackground(PaintEventArgs pevent)
39
{
40
base.OnPaintBackground(pevent);
41
}
42
}
43
}
44

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

当然,现在这个ImageButton除了能显示一张图片以外什么也不能做,我将在后面一步一步完善它。
OnPaint 事件的特性是它可以根据操作系统的要求无限次调用。在实例化和销毁这些对象上浪费时间将会影响绘图性能。 出现所谓的“闪烁”现象,通常采用“双缓冲”来减小这一因素的影响:






























































































































然而,陈现在控件上的一张图片,我们如何让其显示透明图像,为了使图像透明,我们使用下面这个函数来获取图片的背景颜色:





ImageAttributes imageAttr = new ImageAttributes();
imageAttr.SetColorKey(ImageBackColor(this.Image), ImageBackColor(this.Image));
gBuffer.DrawImage(this.Image, imageRect, 0, 0, this.Image.Width, this.Image.Height, GraphicsUnit.Pixel,imageAttr);
imageAttr.SetColorKey(ImageBackColor(this.Image), ImageBackColor(this.Image));
gBuffer.DrawImage(this.Image, imageRect, 0, 0, this.Image.Width, this.Image.Height, GraphicsUnit.Pixel,imageAttr);
这只是一个示例,还有很多不足之处,读者可以自己对其进行扩展,如加入Attributes的支持、为图片在控件中的陈现提供不同的方式(如当图片大于控件的尺寸时,是否对图片进行缩放)等。
http://www.cnblogs.com/nihgwu/archive/2006/07/17/452979.html