C# WinForm开发系列之自定义无边框窗体(最大化,最小化,关闭,拉伸和移动的相关知识)
本片博客主要讲的事最近总结的一些关于窗体的自定义:
1.首先创建一个BaseForm窗体,通过设置属性FormBorderStyle=None为无边框窗体,代码如下:
public partial class BaseForm : Form
{
// 图片名称
public const String IMG_MIN = "btn_min";
public const String IMG_MAX = "btn_max";
public const String IMG_RESTORE = "btn_restore";
public const String IMG_CLOSE = "btn_close";
public const String IMG_BG = "img_bg";
{
// 图片名称
public const String IMG_MIN = "btn_min";
public const String IMG_MAX = "btn_max";
public const String IMG_RESTORE = "btn_restore";
public const String IMG_CLOSE = "btn_close";
public const String IMG_BG = "img_bg";
// 图片缓存
private Bitmap closeBmp = null;
private Bitmap minBmp = null;
private Bitmap maxBmp = null;
private Bitmap restoreBmp = null;
private Bitmap closeBmp = null;
private Bitmap minBmp = null;
private Bitmap maxBmp = null;
private Bitmap restoreBmp = null;
public BaseForm()
{
InitializeComponent();
initForm();
}
{
InitializeComponent();
initForm();
}
// 初始化界面的方法
private void initForm()
{
// 获取最大化、最小化、关闭的背景图片
this.minBmp = ResUtils.GetResAsImage(IMG_MIN);
this.maxBmp = ResUtils.GetResAsImage(IMG_MAX);
this.closeBmp = ResUtils.GetResAsImage(IMG_CLOSE);
this.restoreBmp = ResUtils.GetResAsImage(IMG_RESTORE);
private void initForm()
{
// 获取最大化、最小化、关闭的背景图片
this.minBmp = ResUtils.GetResAsImage(IMG_MIN);
this.maxBmp = ResUtils.GetResAsImage(IMG_MAX);
this.closeBmp = ResUtils.GetResAsImage(IMG_CLOSE);
this.restoreBmp = ResUtils.GetResAsImage(IMG_RESTORE);
// 设置Tip提示信息
this.TipMain.SetToolTip(this.BtnClose, "关闭");
this.TipMain.SetToolTip(this.BtnMin, "最小化");
this.TipMain.SetToolTip(this.BtnMax, "最大化");
if (this.WindowState == FormWindowState.Maximized)
{
this.TipMain.SetToolTip(this.BtnMax, "还原");
this.BtnMax.BackgroundImage = this.restoreBmp;
this.BtnMax.Invalidate();
}
}
this.TipMain.SetToolTip(this.BtnClose, "关闭");
this.TipMain.SetToolTip(this.BtnMin, "最小化");
this.TipMain.SetToolTip(this.BtnMax, "最大化");
if (this.WindowState == FormWindowState.Maximized)
{
this.TipMain.SetToolTip(this.BtnMax, "还原");
this.BtnMax.BackgroundImage = this.restoreBmp;
this.BtnMax.Invalidate();
}
}
// 重写窗体消息轮询方法(不熟悉的可以搜索下win32api)
//protected void WndProc2(ref Message m){//TODO下篇}
//protected void WndProc2(ref Message m){//TODO下篇}
// 鼠标单击(这里为节省代码篇幅将最小化、最大化、关闭的事件统一处理,也可以分单处理)
private void BtnWnd_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (sender == this.BtnClose)
{
this.Close();
}
else if (sender == this.BtnMax)
{
if (this.WindowState == FormWindowState.Normal)
{
this.WindowState = FormWindowState.Maximized;
this.BtnMax.BackgroundImage = this.restoreBmp;
this.TipMain.SetToolTip(this.BtnMax, "还原");
this.BtnMax.Invalidate();
}
else
{
this.WindowState = FormWindowState.Normal;
this.BtnMax.BackgroundImage = this.maxBmp;
this.TipMain.SetToolTip(this.BtnMax, "最大化");
}
}
else if (sender == this.BtnMin)
{
if (!this.ShowInTaskbar)
{
this.Hide();
}
else
{
this.WindowState = FormWindowState.Minimized;
}
}
}
}
private void BtnWnd_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (sender == this.BtnClose)
{
this.Close();
}
else if (sender == this.BtnMax)
{
if (this.WindowState == FormWindowState.Normal)
{
this.WindowState = FormWindowState.Maximized;
this.BtnMax.BackgroundImage = this.restoreBmp;
this.TipMain.SetToolTip(this.BtnMax, "还原");
this.BtnMax.Invalidate();
}
else
{
this.WindowState = FormWindowState.Normal;
this.BtnMax.BackgroundImage = this.maxBmp;
this.TipMain.SetToolTip(this.BtnMax, "最大化");
}
}
else if (sender == this.BtnMin)
{
if (!this.ShowInTaskbar)
{
this.Hide();
}
else
{
this.WindowState = FormWindowState.Minimized;
}
}
}
}
// 鼠标进入
private void BtnWnd_MouseEnter(object sender, EventArgs e)
{
Bitmap backImage = null;
if (sender == this.BtnClose)
{
backImage = ResUtils.GetResWithState(IMG_CLOSE, ControlState.MouseOver);
}
else if (sender == this.BtnMin)
{
backImage = ResUtils.GetResWithState(IMG_MIN, ControlState.MouseOver);
}
else if (sender == this.BtnMax)
{
if (this.WindowState == FormWindowState.Normal)
{
backImage = ResUtils.GetResWithState(IMG_MAX, ControlState.MouseOver);
}
else
{
backImage = ResUtils.GetResWithState(IMG_RESTORE, ControlState.MouseOver);
}
}
else
{
return;
}
Control control = (Control)sender;
control.BackgroundImage = backImage;
control.Invalidate();
}
private void BtnWnd_MouseEnter(object sender, EventArgs e)
{
Bitmap backImage = null;
if (sender == this.BtnClose)
{
backImage = ResUtils.GetResWithState(IMG_CLOSE, ControlState.MouseOver);
}
else if (sender == this.BtnMin)
{
backImage = ResUtils.GetResWithState(IMG_MIN, ControlState.MouseOver);
}
else if (sender == this.BtnMax)
{
if (this.WindowState == FormWindowState.Normal)
{
backImage = ResUtils.GetResWithState(IMG_MAX, ControlState.MouseOver);
}
else
{
backImage = ResUtils.GetResWithState(IMG_RESTORE, ControlState.MouseOver);
}
}
else
{
return;
}
Control control = (Control)sender;
control.BackgroundImage = backImage;
control.Invalidate();
}
// 鼠标移开
private void BtnWnd_MouseLeave(object sender, EventArgs e)
{
Bitmap backImage = null;
if (sender == this.BtnClose)
{
backImage = closeBmp;
}
else if (sender == this.BtnMin)
{
backImage = minBmp;
}
else if (sender == this.BtnMax)
{
if (this.WindowState == FormWindowState.Normal)
{
backImage = maxBmp;
}
else
{
backImage = restoreBmp;
}
}
else
{
return;
}
Control control = (Control)sender;
control.BackgroundImage = backImage;
control.Invalidate();
}
private void BtnWnd_MouseLeave(object sender, EventArgs e)
{
Bitmap backImage = null;
if (sender == this.BtnClose)
{
backImage = closeBmp;
}
else if (sender == this.BtnMin)
{
backImage = minBmp;
}
else if (sender == this.BtnMax)
{
if (this.WindowState == FormWindowState.Normal)
{
backImage = maxBmp;
}
else
{
backImage = restoreBmp;
}
}
else
{
return;
}
Control control = (Control)sender;
control.BackgroundImage = backImage;
control.Invalidate();
}
// 鼠标按下
private void BtnWnd_MouseDown(object sender, MouseEventArgs e)
{
Bitmap backImage = null;
if (sender == this.BtnClose)
{
backImage = ResUtils.GetResWithState(IMG_CLOSE, ControlState.MouseDown);
}
else if (sender == this.BtnMin)
{
backImage = ResUtils.GetResWithState(IMG_MIN, ControlState.MouseDown);
}
else if (sender == this.BtnMax)
{
if (this.WindowState == FormWindowState.Normal)
{
backImage = ResUtils.GetResWithState(IMG_MAX, ControlState.MouseDown);
}
else
{
backImage = ResUtils.GetResWithState(IMG_RESTORE, ControlState.MouseDown);
}
}
else
{
return;
}
Control control = (Control)sender;
control.BackgroundImage = backImage;
control.Invalidate();
}
private void BtnWnd_MouseDown(object sender, MouseEventArgs e)
{
Bitmap backImage = null;
if (sender == this.BtnClose)
{
backImage = ResUtils.GetResWithState(IMG_CLOSE, ControlState.MouseDown);
}
else if (sender == this.BtnMin)
{
backImage = ResUtils.GetResWithState(IMG_MIN, ControlState.MouseDown);
}
else if (sender == this.BtnMax)
{
if (this.WindowState == FormWindowState.Normal)
{
backImage = ResUtils.GetResWithState(IMG_MAX, ControlState.MouseDown);
}
else
{
backImage = ResUtils.GetResWithState(IMG_RESTORE, ControlState.MouseDown);
}
}
else
{
return;
}
Control control = (Control)sender;
control.BackgroundImage = backImage;
control.Invalidate();
}
// 鼠标弹起
private void BtnWnd_MouseUp(object sender, MouseEventArgs e)
{
Bitmap backImage = null;
if (sender == this.BtnClose)
{
backImage = closeBmp;
}
else if (sender == this.BtnMin)
{
backImage = minBmp;
}
else if (sender == this.BtnMax)
{
if (this.WindowState == FormWindowState.Normal)
{
backImage = maxBmp;
}
else
{
backImage = restoreBmp;
}
}
else
{
return;
}
Control control = (Control)sender;
control.BackgroundImage = backImage;
control.Invalidate();
}
private void BtnWnd_MouseUp(object sender, MouseEventArgs e)
{
Bitmap backImage = null;
if (sender == this.BtnClose)
{
backImage = closeBmp;
}
else if (sender == this.BtnMin)
{
backImage = minBmp;
}
else if (sender == this.BtnMax)
{
if (this.WindowState == FormWindowState.Normal)
{
backImage = maxBmp;
}
else
{
backImage = restoreBmp;
}
}
else
{
return;
}
Control control = (Control)sender;
control.BackgroundImage = backImage;
control.Invalidate();
}
}
窗体如下图1所示:
图1
2.创建Form1窗体,继承BaseForm表单,
正常运行运行结果如下图2所示:
图2
点击放大按钮如图3所示:
图3
3,此时自定义的窗体只能放大,缩小和关闭,若要使窗体可移动,代码如下:
//窗体移动相关常量设置
const int Guying_HTLEFT = 10;
const int Guying_HTRIGHT = 11;
const int Guying_HTTOP = 12;
const int Guying_HTTOPLEFT = 13;
const int Guying_HTTOPRIGHT = 14;
const int Guying_HTBOTTOM = 15;
const int Guying_HTBOTTOMLEFT = 0x10;
const int Guying_HTBOTTOMRIGHT = 17;
const int Guying_HTLEFT = 10;
const int Guying_HTRIGHT = 11;
const int Guying_HTTOP = 12;
const int Guying_HTTOPLEFT = 13;
const int Guying_HTTOPRIGHT = 14;
const int Guying_HTBOTTOM = 15;
const int Guying_HTBOTTOMLEFT = 0x10;
const int Guying_HTBOTTOMRIGHT = 17;
////重写系统WndProc函数,使无边框窗体可移动
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case 0x0084:
base.WndProc(ref m);
Point vPoint = new Point((int)m.LParam & 0xFFFF,
(int)m.LParam >> 16 & 0xFFFF);
vPoint = PointToClient(vPoint);
if (vPoint.X <= 5)
if (vPoint.Y <= 5)
m.Result = (IntPtr)Guying_HTTOPLEFT;
else if (vPoint.Y >= ClientSize.Height - 5)
m.Result = (IntPtr)Guying_HTBOTTOMLEFT;
else m.Result = (IntPtr)Guying_HTLEFT;
else if (vPoint.X >= ClientSize.Width - 5)
if (vPoint.Y <= 5)
m.Result = (IntPtr)Guying_HTTOPRIGHT;
else if (vPoint.Y >= ClientSize.Height - 5)
m.Result = (IntPtr)Guying_HTBOTTOMRIGHT;
else m.Result = (IntPtr)Guying_HTRIGHT;
else if (vPoint.Y <= 5)
m.Result = (IntPtr)Guying_HTTOP;
else if (vPoint.Y >= ClientSize.Height - 5)
m.Result = (IntPtr)Guying_HTBOTTOM;
break;
case 0x0201: //鼠标左键按下的消息
m.Msg = 0x00A1; //更改消息为非客户区按下鼠标
m.LParam = IntPtr.Zero; //默认值
m.WParam = new IntPtr(2);//鼠标放在标题栏内
base.WndProc(ref m);
break;
default:
base.WndProc(ref m);
break;
}
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case 0x0084:
base.WndProc(ref m);
Point vPoint = new Point((int)m.LParam & 0xFFFF,
(int)m.LParam >> 16 & 0xFFFF);
vPoint = PointToClient(vPoint);
if (vPoint.X <= 5)
if (vPoint.Y <= 5)
m.Result = (IntPtr)Guying_HTTOPLEFT;
else if (vPoint.Y >= ClientSize.Height - 5)
m.Result = (IntPtr)Guying_HTBOTTOMLEFT;
else m.Result = (IntPtr)Guying_HTLEFT;
else if (vPoint.X >= ClientSize.Width - 5)
if (vPoint.Y <= 5)
m.Result = (IntPtr)Guying_HTTOPRIGHT;
else if (vPoint.Y >= ClientSize.Height - 5)
m.Result = (IntPtr)Guying_HTBOTTOMRIGHT;
else m.Result = (IntPtr)Guying_HTRIGHT;
else if (vPoint.Y <= 5)
m.Result = (IntPtr)Guying_HTTOP;
else if (vPoint.Y >= ClientSize.Height - 5)
m.Result = (IntPtr)Guying_HTBOTTOM;
break;
case 0x0201: //鼠标左键按下的消息
m.Msg = 0x00A1; //更改消息为非客户区按下鼠标
m.LParam = IntPtr.Zero; //默认值
m.WParam = new IntPtr(2);//鼠标放在标题栏内
base.WndProc(ref m);
break;
default:
base.WndProc(ref m);
break;
}
}
运行代码后,效果如图4,图5,图6所示:
图4
图5
图6
注意: