按钮控件Button
button类里的Image属性成员可以指定按钮显示的图片,相比MFC,.net里的控件可设置的属性多了许多,这样一般不需要自绘就能使控件
的外观变得丰富多彩起来。随便设置几张图片就可以了,只要在图片上下功夫就行了。
看一个示例吧,首先准备一张按钮显示的图片:
button.jpg 125x33大小
然后往Form窗体里添加一个按钮控件,记住按钮控件要跟图片一样大小,因为Button类是不会自动缩放或者放大图片的。
示例代码如下:
public Form1()
{
InitializeComponent();
//按钮大小
button1.Width = 125;
button1.Height = 33;
//按钮显示的文本
button1.Text = "确 定";
//按钮文本的字体
button1.Font = new Font("宋体", 15f);
//文本的颜色
button1.ForeColor = Color.White;
//按钮显示的图片
button1.Image= Image.FromFile("d:\\Image\\button.jpg");
}
效果图:
如果想要不同状态显示不同的图片的话,那就添加按钮事件处理函数:MouseEnter鼠标进入控件,MouseLeave鼠标离开控件,
MouseDown在控件里按下了鼠标键,MouseUp在控件里松开了鼠标键。在这些事件里更改Image属性。
完成上面的功能,需要准备三张图片。
buttonNor.jpg 按钮正常状态下显示的图片
buttonDown.jpg 按钮按下时显示的图片
buttonHov.jpg 鼠标停留在按钮上显示的图片
代码如下:
public partial class Form1 : Form
{
//三张不同状态的图片
public Image imgNormal = Image.FromFile("d:\\Image\\buttonNor.jpg");
public Image imgDown = Image.FromFile("d:\\Image\\buttonDown.jpg");
public Image imgHover = Image.FromFile("d:\\Image\\buttonHov.jpg");
public Form1()
{
InitializeComponent();
//按钮大小
button1.Width = 125;
button1.Height = 33;
//按钮显示的文本
button1.Text = "确 定";
//按钮文本的字体
button1.Font = new Font("宋体", 15f);
//文本的颜色
button1.ForeColor = Color.White;
//按钮显示的图片
//添加四个事件处理函数
button1.Image= imgNormal;
button1.MouseEnter+=btnMouseEnter;
button1.MouseLeave+=btnMouseLeave;
button1.MouseDown+=btnMouseDown;
button1.MouseUp += btnMouseUp;
}
//四个事件处理函数
private void btnMouseEnter(object sender, EventArgs e)
{
button1.Image = imgHover;
}
private void btnMouseLeave(object sender, EventArgs e)
{
button1.Image = imgNormal;
}
private void btnMouseDown(object sender, MouseEventArgs e)
{
button1.Image = imgDown;
}
private void btnMouseUp(object sender, MouseEventArgs e)
{
button1.Image = imgHover;
}
}
按钮控件自绘:
如果需要自绘按钮控件,就不能通过添加事件的方式了,因为这样虽然也可以参与绘制,但Button类默认也绘制了,这样就不可避免的会起冲突。而且影响效率,比如按钮按下,系统默认绘制其状态,然后你又重新绘制。那么默认的绘制完全没必要。
所以我们不让能基类来处理某些事件,要怎么实现呢,重写基类的事件处理函数就可以了。
这个在《GDI+编程(一)》里的绘制背景中已经说明过了。
看例子吧,我省了很多事,只把关键点说出来。连按钮的文本都没绘制,只是简单的绘制几张图片。
给项目工程添加一个MyButton.cs文件,这个文件里的代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace WindowsApplication2
{
public class MyButton:Button
{
//按钮三种状态的图片
public Image imgNormal = Image.FromFile("d:\\Image\\buttonNor.jpg");
public Image imgDown = Image.FromFile("d:\\Image\\buttonDown.jpg");
public Image imgHover = Image.FromFile("d:\\Image\\buttonHov.jpg");
//全部禁止默认处理函数处理这些事件
protected override void OnMouseEnter(EventArgs e)
{
//base.OnMouseEnter(e);
CreateGraphics().DrawImage(imgHover, new Rectangle(0, 0, Width, Height));
}
protected override void OnMouseLeave(EventArgs e)
{
//base.OnMouseLeave(e);
CreateGraphics().DrawImage(imgNormal, new Rectangle(0, 0, Width, Height));
}
protected override void OnMouseDown(MouseEventArgs mevent)
{
// base.OnMouseDown(mevent);
CreateGraphics().DrawImage(imgDown, new Rectangle(0, 0, Width, Height));
}
protected override void OnMouseUp(MouseEventArgs mevent)
{
// base.OnMouseUp(mevent);
CreateGraphics().DrawImage(imgHover, new Rectangle(0, 0, Width, Height));
EventArgs e = new EventArgs();
base.OnClick(e);
}
protected override void OnPaint(PaintEventArgs pevent)
{
//base.OnPaint(pevent);
//只绘制一个正常状态,其它状态就不绘制了
pevent.Graphics.DrawImage(imgNormal, new Rectangle(0, 0, Width, Height));
}
}
}
在OnMouseUp调用了OnClick,是因为禁止了基类处理MouseUp事件,那么它就监测不到单击的事件,这样通过Click添加的处理函数,都不会被执行。
所以在这里调用OnClick。另外Paint事件也是一样的。
Form1类的部分代码:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//创建按钮
button1 = new MyButton();
button1.Location = new Point(50, 50);
button1.Size = new Size(90, 35);
this.Controls.Add(button1);
}
public MyButton button1;
}
自绘组合框
给组合框添加DrawItem事件处理函数,就可以自绘组合框,这个DrawItem事件跟MFC里的WM_DRAWITEM消息有点类似,它们的绘制方式都没相差多少。
DrawItem事件处理函数的定义:
private void ComboBox1_DrawItem(object sender, DrawItemEventArgs e)
参数e存储有项各的信息,比如e.State项的状态,e.Bounds一个项的矩形区域。
这个自绘组框要实现项对应的图片绘制,也就是实现可以给一个项关联图片的功能,那么就要给每一个项自定义数据了。但不像MFC组合框
的类,可以调用SetItemData函数给一个项关联自定义数据。.net里面的ComboBox可没类似的功能。
但是我们在添加项的时候发现,comboBox1.Items.Add函数的参数都是Object类型,这样我们就可以自定义一个类,描述项的信息。
这个类对象当然也可以转换成Object类型,因为所有的类都是从Object派生出来的。
关键代码如下:(记得准备五张图片,用于项图片显示)
//自定义组合框项
public class MyItem
{
//项文本内容
private String Text;
//项图片
public Image Img;
public MyItem(String text, Image img)
{
Text = text;
Img = img;
}
//重写ToString函数,返回项文本
public override string ToString()
{
return Text;
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//添加项
comboBox1.Items.Add(new MyItem("1111111", Image.FromFile("d:\\Image\\qq1.jpg")));
comboBox1.Items.Add(new MyItem("2222222", Image.FromFile("d:\\Image\\qq2.jpg")));
comboBox1.Items.Add(new MyItem("3333333", Image.FromFile("d:\\Image\\qq3.jpg")));
comboBox1.Items.Add(new MyItem("4444444", Image.FromFile("d:\\Image\\qq4.jpg")));
comboBox1.Items.Add(new MyItem("5555555", Image.FromFile("d:\\Image\\qq5.jpg")));
//默认选中项索引
comboBox1.SelectedIndex = 0;
//自绘组合框需要设置的一些属性
comboBox1.DrawMode = DrawMode.OwnerDrawVariable;
comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
comboBox1.ItemHeight = 30;
comboBox1.Width = 200;
//添加DrawItem事件处理函数
comboBox1.DrawItem += ComboBox1_DrawItem;
}
private void ComboBox1_DrawItem(object sender, DrawItemEventArgs e)
{
if ((e.State & DrawItemState.Selected) != 0)//鼠标选中在这个项上
{
//渐变画刷
LinearGradientBrush brush = new LinearGradientBrush(e.Bounds, Color.FromArgb(255, 251, 237),
Color.FromArgb(255, 236, 181),LinearGradientMode.Vertical);
//填充区域
Rectangle borderRect = new Rectangle(3, e.Bounds.Y + 1, e.Bounds.Width - 5, e.Bounds.Height - 2);
e.Graphics.FillRectangle(brush, borderRect);
//画边框
Pen pen = new Pen(Color.FromArgb(229, 195, 101));
e.Graphics.DrawRectangle(pen, borderRect);
}
else
{
SolidBrush brush = new SolidBrush(Color.FromArgb(217,223,230));
e.Graphics.FillRectangle(brush, e.Bounds);
}
//获得项图片,绘制图片
MyItem item=(MyItem)comboBox1.Items[e.Index];
Image img = item.Img;
//图片绘制的区域
Rectangle imgRect = new Rectangle(6, e.Bounds.Y+3, 25, 25);
e.Graphics.DrawImage(img, imgRect);
//文本内容显示区域
Rectangle textRect =
new Rectangle(imgRect.Right + 2, imgRect.Y, e.Bounds.Width - imgRect.Width, e.Bounds.Height-2);
//获得项文本内容,绘制文本
String itemText = comboBox1.Items[e.Index].ToString();
//文本格式垂直居中
StringFormat strFormat=new StringFormat();
strFormat.LineAlignment=StringAlignment.Center;
e.Graphics.DrawString(itemText, new Font("宋体", 12), Brushes.Black, textRect, strFormat);
}
}
效果图:
上面的只是简单的自绘了下,如果要好好自绘一下ComboBox类,可以从ComboBox类派生出一个新类自绘。