在Windows Forms应用程序中,经常需要对控件的外观进行自定义,以满足特定的设计需求。本文将介绍如何为窗体和按钮创建自定义的位图区域,并实现鼠标悬停时的图像变化效果。
以下是用于创建位图区域的两个主要函数的代码。这些函数位于名为BitmapRegion.cs的文件中。
创建和应用控件区域的函数:
public static void CreateControlRegion(Control control, Bitmap bitmap)
{
if (control == null || bitmap == null)
return;
control.Width = bitmap.Width;
control.Height = bitmap.Height;
if (control is System.Windows.Forms.Form)
{
Form form = (Form)control;
form.Width += 15;
form.Height += 35;
form.FormBorderStyle = FormBorderStyle.None;
form.BackgroundImage = bitmap;
GraphicsPath graphicsPath = CalculateControlGraphicsPath(bitmap);
form.Region = new Region(graphicsPath);
}
else if (control is System.Windows.Forms.Button)
{
Button button = (Button)control;
button.Text = "";
button.Cursor = Cursors.Hand;
button.BackgroundImage = bitmap;
GraphicsPath graphicsPath = CalculateControlGraphicsPath(bitmap);
button.Region = new Region(graphicsPath);
}
}
计算控件图形路径的函数:
private static GraphicsPath CalculateControlGraphicsPath(Bitmap bitmap)
{
GraphicsPath graphicsPath = new GraphicsPath();
Color colorTransparent = bitmap.GetPixel(0, 0);
int colOpaquePixel = 0;
for (int row = 0; row < bitmap.Height; row++)
{
colOpaquePixel = 0;
for (int col = 0; col < bitmap.Width; col++)
{
if (bitmap.GetPixel(col, row) != colorTransparent)
{
colOpaquePixel = col;
int colNext = col;
for (colNext = colOpaquePixel; colNext < bitmap.Width; colNext++)
{
if (bitmap.GetPixel(colNext, row) == colorTransparent)
break;
}
graphicsPath.AddRectangle(new Rectangle(colOpaquePixel, row, colNext - colOpaquePixel, 1));
col = colNext;
}
}
}
return graphicsPath;
}
为窗体创建位图区域:
要为窗体创建位图区域,只需要以下两行代码。注意,不需要显式地将窗体的边框设置为无,因为这将为完成。
public class Form1 : System.Windows.Forms.Form
{
private Bitmap bmpFrmBack = new Bitmap(typeof(Form1), "back.bmp");
public Form1()
{
InitializeComponent();
BitmapRegion.CreateControlRegion(this, bmpFrmBack);
}
}
为按钮创建位图区域:
为按钮创建位图区域与窗体相同。同样,不需要对按钮的样式做任何更改。
public class Form1 : System.Windows.Forms.Form
{
private Bitmap bmpFrmBack = new Bitmap(typeof(Form1), "back.bmp");
private Bitmap bmpBob = new Bitmap(typeof(Form1), "bob.bmp");
public Form1()
{
InitializeComponent();
BitmapRegion.CreateControlRegion(this, bmpFrmBack);
BitmapRegion.CreateControlRegion(button1, bmpBob);
}
}
实现鼠标悬停效果:
如果想在鼠标悬停在按钮上时改变按钮的位图,不需要创建自定义按钮控件。只需要简单地处理MouseEnter和MouseLeave事件,如下所示。
private void button1_MouseEnter(object sender, System.EventArgs e)
{
BitmapRegion.CreateControlRegion(button1, bmpBobSay);
}
private void button1_MouseLeave(object sender, System.EventArgs e)
{
BitmapRegion.CreateControlRegion(button1, bmpBob);
}
拖动窗体:
由于窗体现在没有标题栏,需要使其能够在窗体的任何地方点击并拖动。MFC版本中使用的解决方案是处理WM_LBUTTONDOWN并执行PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(point.x,point.y))来欺骗Windows认为点击了标题栏。然而,无法在Windows Forms中实现这一点,因此下面的代码是另一种解决方案。
private void Form1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (isFirst == true)
{
prevLeftClick = new Point(e.X, e.Y);
isFirst = false;
}
else
{
if (toBlock == false)
{
this.Location = new Point(this.Location.X + e.X - prevLeftClick.X, this.Location.Y + e.Y - prevLeftClick.Y);
prevLeftClick = new Point(e.X, e.Y);
toBlock = !toBlock;
}
}
}
else
{
isFirst = true;
}
}