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);
- }
- }
- }