1.直接使用编译好的PicButton.dll在项目中添加引用,在"工具栏"--右键--选择项--.NET Framework 组件--浏览--找到PicButton添加--PicButton图片按钮在工具栏中
2.在项目中编辑PicButton项目,其实上边方法的dll文件 就是在这里编译出来的具体实现方法:
1.在项目中在重新新建一个项目(添加类库),如下图中PicButton类库
添加完后:
添加引用,并编辑class1.cs,如下:
class1.cs修改后如下,当把class1修改为继承Control时,注意到Class1的文件标志发生了变化:
然后生成项目,可以看到在窗口上看到Class1控件(也可以根据需要改成自己喜欢的名字),将其添加到窗体上改写
- using System;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.Windows.Forms;
- using System.Collections.Generic;
- using System.Text;
- using System.ComponentModel;
- using System.Runtime.InteropServices;
- namespace PicButton
- {
- public class Class1:Control
- {
- //私有成员
- private Image imageOri, imageHover;
- //表示按下状态的标记
- private bool bPushed, bHovered;
- //缓冲位图
- private Bitmap m_bmpOffscreen;
- //是否自动调整控件大小,以适合不同大小的图片
- private bool bAutoSetSize;
- public Class1():base()
- {
- bPushed = false;
- bHovered = false;
- bAutoSetSize = true;
- }
- [Description("默认的的图片,大小应与ImageHover一致"), Category("自定义")]
- public Image ImageOri
- {
- get
- {
- return imageOri;
- }
- set
- { imageOri = value;
- if (bAutoSetSize)
- SetSizeToImage(value);
- this.Invalidate();
- }
- }
- [Description("鼠标悬停时的图片,大小应与ImageOriginal一致"), Category("自定义")]
- public Image ImageHover
- {
- get
- { return imageHover;
- }
- set
- { imageHover = value;
- if (bAutoSetSize)
- SetSizeToImage(value);
- this.Invalidate();
- }
- }
- [Description("是否自动调整以适应ImageOri的大小"), Category("自定义")]
- public bool AutoSetSize
- { get
- { return bAutoSetSize;
- }
- set
- {
- bAutoSetSize = value;
- if (bAutoSetSize)
- {
- SetSizeToImage(this.imageOri);
- }
- }
- }
- protected override void OnPaintBackground(PaintEventArgs e)
- {
- //不执行任何操作
- }
- protected override void OnClick(EventArgs e)
- {
- //触发Click事件前更新UI,避免事件处理完毕才响应UI
- this.bPushed = false;
- this.bHovered = true;
- this.Refresh();
- base.OnClick(e);
- }
- protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
- {
- base.OnPaint(e);
- Graphics gxOff; //屏幕外的图像
- Rectangle imgRect; //图像矩形
- if (imageOri == null)
- {
- e.Graphics.Clear(this.BackColor);
- return;
- }
- if (m_bmpOffscreen == null) //要双缓冲的位图
- {//见OnResize方法
- m_bmpOffscreen = new Bitmap(ClientSize.Width, ClientSize.Height);
- }
- gxOff = Graphics.FromImage(m_bmpOffscreen);
- gxOff.Clear(Parent.BackColor);
- ImageAttributes imageAttr = new ImageAttributes();
- Image imageNow = imageOri;
- //将图像相对于控件居中
- imgRect = new Rectangle((this.Width - imageNow.Width) / 2, (this.Height - imageNow.Height) / 2,
- imageNow.Width, imageNow.Height);
- if (this.Enabled && bPushed && imageHover != null)
- {
- imageNow = imageHover;
- imgRect = new Rectangle((this.Width - imageNow.Width) / 2, (this.Height - imageNow.Height) / 2,
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace PicButton
{
public class Class1:Control
{
//私有成员
private Image imageOri, imageHover;
//表示按下状态的标记
private bool bPushed, bHovered;
//缓冲位图
private Bitmap m_bmpOffscreen;
//是否自动调整控件大小,以适合不同大小的图片
private bool bAutoSetSize;
public Class1():base()
{
bPushed = false;
bHovered = false;
bAutoSetSize = true;
}
[Description("默认的的图片,大小应与ImageHover一致"), Category("自定义")]
public Image ImageOri
{
get
{
return imageOri;
}
set
{ imageOri = value;
if (bAutoSetSize)
SetSizeToImage(value);
this.Invalidate();
}
}
[Description("鼠标悬停时的图片,大小应与ImageOriginal一致"), Category("自定义")]
public Image ImageHover
{
get
{ return imageHover;
}
set
{ imageHover = value;
if (bAutoSetSize)
SetSizeToImage(value);
this.Invalidate();
}
}
[Description("是否自动调整以适应ImageOri的大小"), Category("自定义")]
public bool AutoSetSize
{ get
{ return bAutoSetSize;
}
set
{
bAutoSetSize = value;
if (bAutoSetSize)
{
SetSizeToImage(this.imageOri);
}
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
//不执行任何操作
}
protected override void OnClick(EventArgs e)
{
//触发Click事件前更新UI,避免事件处理完毕才响应UI
this.bPushed = false;
this.bHovered = true;
this.Refresh();
base.OnClick(e);
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
base.OnPaint(e);
Graphics gxOff; //屏幕外的图像
Rectangle imgRect; //图像矩形
if (imageOri == null)
{
e.Graphics.Clear(this.BackColor);
return;
}
if (m_bmpOffscreen == null) //要双缓冲的位图
{//见OnResize方法
m_bmpOffscreen = new Bitmap(ClientSize.Width, ClientSize.Height);
}
gxOff = Graphics.FromImage(m_bmpOffscreen);
gxOff.Clear(Parent.BackColor);
ImageAttributes imageAttr = new ImageAttributes();
Image imageNow = imageOri;
//将图像相对于控件居中
imgRect = new Rectangle((this.Width - imageNow.Width) / 2, (this.Height - imageNow.Height) / 2,
imageNow.Width, imageNow.Height);
if (this.Enabled && bPushed && imageHover != null)
{
imageNow = imageHover;
imgRect = new Rectangle((this.Width - imageNow.Width) / 2, (this.Height - imageNow.Height) / 2,
- imageNow.Width, imageNow.Height);
- imgRect.Offset(1, 1);
- }
- else if (this.Enabled && bHovered && imageHover != null)
- {
- imageNow = imageHover;
- }
- imageAttr.SetColorKey(BackgroundImageColor(imageNow), BackgroundImageColor(imageNow));
- //如果不可用,使用变换办法,将当前图象变换为灰度
- if (!this.Enabled)
- GetColorTrans(imageAttr);
- //绘制图像
- gxOff.DrawImage(imageNow, imgRect, 0, 0, imageNow.Width, imageNow.Height, GraphicsUnit.Pixel, imageAttr);
- //从内存位图绘制
- e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);
- gxOff.Dispose();
- gxOff = null;
- private void SetSizeToImage(Image img)
- {
- if (img != null)
- {
- System.Drawing.Rectangle r = new Rectangle(0, 0, img.Width, img.Height);
- r.Inflate(2, 2);
- this.Width = r.Width;
- this.Height = r.Height;
- }
- }
- private Color BackgroundImageColor(Image image)
- {
- Bitmap bmp = new Bitmap(image);
- return bmp.GetPixel(0, 0);
- }
- private void GetColorTrans(ImageAttributes imageAttributes)
- {
- //将当前r,g,b彩色分量按公式grey = r * 0.39 + g * 0.50 + b * 0.11进行变换
- //注意是 r=grey,g=grey,b=grey
- float[][] colorMatrixElements = {
- new float[] {0.39f, 0.39f, 0.39f, 0, 0}, // red scaling factor of 2
- new float[] {0.50f, 0.50f, 0.50f, 0, 0}, // green scaling factor of 1
- new float[] {0.11f, 0.11f, 0.11f, 0, 0}, // blue scaling factor of 1
- new float[] {0, 0, 0, 1, 0}, // alpha scaling factor of 1
- new float[] {0, 0, 0, 0, 1}}; // three translations of 0.2
- ColorMatrix colorMatrix = new ColorMatrix(colorMatrixElements);
- imageAttributes.SetColorMatrix(
- colorMatrix,
- ColorMatrixFlag.Default,
- ColorAdjustType.Bitmap);
imageNow.Width, imageNow.Height);
imgRect.Offset(1, 1);
}
else if (this.Enabled && bHovered && imageHover != null)
{
imageNow = imageHover;
}
imageAttr.SetColorKey(BackgroundImageColor(imageNow), BackgroundImageColor(imageNow));
//如果不可用,使用变换办法,将当前图象变换为灰度
if (!this.Enabled)
GetColorTrans(imageAttr);
//绘制图像
gxOff.DrawImage(imageNow, imgRect, 0, 0, imageNow.Width, imageNow.Height, GraphicsUnit.Pixel, imageAttr);
//从内存位图绘制
e.Graphics.DrawImage(m_bmpOffscreen, 0, 0);
gxOff.Dispose();
gxOff = null;
}
private void SetSizeToImage(Image img)
{
if (img != null)
{
System.Drawing.Rectangle r = new Rectangle(0, 0, img.Width, img.Height);
r.Inflate(2, 2);
this.Width = r.Width;
this.Height = r.Height;
}
}
private Color BackgroundImageColor(Image image)
{
Bitmap bmp = new Bitmap(image);
return bmp.GetPixel(0, 0);
}
private void GetColorTrans(ImageAttributes imageAttributes)
{
//将当前r,g,b彩色分量按公式grey = r * 0.39 + g * 0.50 + b * 0.11进行变换
//注意是 r=grey,g=grey,b=grey
float[][] colorMatrixElements = {
new float[] {0.39f, 0.39f, 0.39f, 0, 0}, // red scaling factor of 2
new float[] {0.50f, 0.50f, 0.50f, 0, 0}, // green scaling factor of 1
new float[] {0.11f, 0.11f, 0.11f, 0, 0}, // blue scaling factor of 1
new float[] {0, 0, 0, 1, 0}, // alpha scaling factor of 1
new float[] {0, 0, 0, 0, 1}}; // three translations of 0.2
ColorMatrix colorMatrix = new ColorMatrix(colorMatrixElements);
imageAttributes.SetColorMatrix(
colorMatrix,
ColorMatrixFlag.Default,
ColorAdjustType.Bitmap);
- }
- public new bool Enabled
- {
- get { return base.Enabled; }
- set
- {
- base.Enabled = value;
- this.Invalidate();
- }
- protected override void OnMouseEnter(EventArgs e)
- {
- base.OnMouseEnter(e);
- bHovered = true;
- this.Invalidate();
- }
- protected override void OnMouseLeave(EventArgs e)
- {
- base.OnMouseLeave(e);
- bHovered = false;
- this.Invalidate();
}
public new bool Enabled
{
get { return base.Enabled; }
set
{
base.Enabled = value;
this.Invalidate();
}
}
protected override void OnMouseEnter(EventArgs e)
{
base.OnMouseEnter(e);
bHovered = true;
this.Invalidate();
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
bHovered = false;
this.Invalidate();
- }
- protected override void OnMouseMove(MouseEventArgs e)
- {//鼠标处于按下状态时移到客户区之外仍会接收Move消息,但不会接收Leave消息
- //因此需要在Move消息中判断当前鼠标是否在客户区内,并触发相应的OnMouseLeave或OnMouseEnter
- base.OnMouseMove(e);
- if (e.Button == MouseButtons.Left)
- {
- if (!this.ClientRectangle.Contains(e.X, e.Y))
- {//鼠标处于按下状态时从客户区内移到客户区之外时,模拟OnMouseLeave
- if (this.bHovered)
- {
- this.bPushed = false;
- OnMouseLeave(EventArgs.Empty);
- }
- }
- else
- {//鼠标处于按下状态时从客户区内移到客户区之外,再移回客户区内时,模拟OnMouseEnter,同时bPushed = true
- if (!this.bHovered)
- bPushed = true;
- OnMouseEnter(EventArgs.Empty);
- }
- }//以下为增加的处理:
- else
- {//***模拟OnMouseEnter,参见 关于空闲处理的必要性
- if (bHovered == false)
- {//***收得到Move消息时鼠标也不一定是在客户区内,必须进行if (this.ClientRectangle.Contains(e.X, e.Y))判断
- if (this.ClientRectangle.Contains(e.X, e.Y))
}
protected override void OnMouseMove(MouseEventArgs e)
{//鼠标处于按下状态时移到客户区之外仍会接收Move消息,但不会接收Leave消息
//因此需要在Move消息中判断当前鼠标是否在客户区内,并触发相应的OnMouseLeave或OnMouseEnter
base.OnMouseMove(e);
if (e.Button == MouseButtons.Left)
{
if (!this.ClientRectangle.Contains(e.X, e.Y))
{//鼠标处于按下状态时从客户区内移到客户区之外时,模拟OnMouseLeave
if (this.bHovered)
{
this.bPushed = false;
OnMouseLeave(EventArgs.Empty);
}
}
else
{//鼠标处于按下状态时从客户区内移到客户区之外,再移回客户区内时,模拟OnMouseEnter,同时bPushed = true
if (!this.bHovered)
bPushed = true;
OnMouseEnter(EventArgs.Empty);
}
}//以下为增加的处理:
else
{//***模拟OnMouseEnter,参见 关于空闲处理的必要性
if (bHovered == false)
{//***收得到Move消息时鼠标也不一定是在客户区内,必须进行if (this.ClientRectangle.Contains(e.X, e.Y))判断
if (this.ClientRectangle.Contains(e.X, e.Y))
- {
- bHovered = true;
- this.Invalidate();
- }
- }
- }
- }
- protected override void OnResize(EventArgs e)
- {
- base.OnResize(e);
- /*重要,为节省资源,不在每次paint时都调用生成缓冲位图
- * 但在大小改变时必须重新生成新的大小的m_bmpOffscreen以适应新的大小
- */
- m_bmpOffscreen = null;
- this.Invalidate();
- }
- protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
- {
- base.OnMouseDown(e);
- if (e.Button == MouseButtons.Left)
- {
- bPushed = true;
- this.Invalidate();
- }
- }
- protected override void OnMouseUp(System.Windows.Forms.MouseEventArgs e)
- { base.OnMouseUp(e);
- bPushed = false;
- this.Invalidate();
- }
- public void PerformClick()
- {
- this.OnClick(EventArgs.Empty);
- }
- }
- }