c#怎么使windows窗口美化
2016-08-14
展开全部
一:窗体圆角的处理
对于无边框窗体圆角矩形的处理,我这里采用的是使用API函数CreateRoundRectRgn,相比于自己用GDI+写的处理圆角的函数,效果要稍微好点,至少线条在圆角处过渡的比较平滑,为了便于复用,我把其封装到窗体自绘辅助类RenderHlper的SetFormRoundRectRgn函数中:
View Code
/// <summary>
/// 设置窗体的圆角矩形
/// </summary>
/// <param name="form">需要设置的窗体</param>
/// <param name="rgnRadius">圆角矩形的半径</param>
public static void SetFormRoundRectRgn(Form form, int rgnRadius)
{
int hRgn = 0;
hRgn = Win32.CreateRoundRectRgn(0, 0, form.Width + 1, form.Height + 1, rgnRadius, rgnRadius);
Win32.SetWindowRgn(form.Handle, hRgn, true);
Win32.DeleteObject(hRgn);
}
此处需要把所需要的API函数引用到类Win32中,引用的时候注意添加 System.Runtime.InteropServices 命名空间:
View Code
[DllImport("gdi32.dll")]
public static extern int CreateRoundRectRgn(int x1, int y1, int x2, int y2, int x3, int y3);
[DllImport("user32.dll")]
public static extern int SetWindowRgn(IntPtr hwnd, int hRgn, Boolean bRedraw);
[DllImport("gdi32.dll", EntryPoint = "DeleteObject", CharSet = CharSet.Ansi)]
public static extern int DeleteObject(int hObject);
重写窗体的OnSizeChanged事件,并在此事件中调用SetFormRoundRectRgn,此处的Radius参数为定义的窗体圆角半径属性:
View Code
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
RenderHelper.SetFormRoundRectRgn(this, Radius);
}
二:无边框窗体大小的改变与移动
当把窗体的FormBorderStyle属性调整为FormBorderStyle.None时,此时,窗体的大小改变不了,同时窗体不能移动。要想实现无边框窗体大小的改变与移动,可采用如下方法:
(1)重写窗体的过程WndProc:
主要是对WM_NCHITTEST消息进行处理,根据事件的发生位置来进行不同方向箭头的调整,窗体大小改变与移动的函数:
View Code
//调整窗体大小
private void WmNcHitTest(ref Message m)
{
int wparam = m.LParam.ToInt32();
Point mouseLocation = new Point(RenderHelper.LOWORD(wparam),RenderHelper.HIWORD(wparam));
mouseLocation = PointToClient(mouseLocation);
if (WindowState != FormWindowState.Maximized )
{
if (CanResize == true)
{
if (mouseLocation.X < 5 && mouseLocation.Y < 5)
{
m.Result = new IntPtr(Win32.HTTOPLEFT);
return;
}
if (mouseLocation.X > Width - 5 && mouseLocation.Y < 5)
{
m.Result = new IntPtr(Win32.HTTOPRIGHT);
return;
}
if (mouseLocation.X < 5 && mouseLocation.Y > Height - 5)
{
m.Result = new IntPtr(Win32.HTBOTTOMLEFT);
return;
}
if (mouseLocation.X > Width - 5 && mouseLocation.Y > Height - 5)
{
m.Result = new IntPtr(Win32.HTBOTTOMRIGHT);
return;
}
if (mouseLocation.Y < 3)
{
m.Result = new IntPtr(Win32.HTTOP);
return;
}
if (mouseLocation.Y > Height - 3)
{
m.Result = new IntPtr(Win32.HTBOTTOM);
return;
}
if (mouseLocation.X < 3)
{
m.Result = new IntPtr(Win32.HTLEFT);
return;
}
if (mouseLocation.X > Width - 3)
{
m.Result = new IntPtr(Win32.HTRIGHT);
return;
}
}
}
m.Result = new IntPtr(Win32.HTCAPTION);
}
重写窗体过程:
View Code
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case Win32.WM_NCHITTEST:
WmNcHitTest(ref m);
break;
default:
base.WndProc(ref m);
break;
}
}
(2)对于仅仅只想实现窗体的移动而不改变窗体的大小,可以重写OnMouseDown事件中发送HTCAPTION消息来实现无边框窗体的移动,具体的实现代码如下:
View Code
/// <summary>
/// 移动窗体
/// </summary>
public static void MoveWindow(Form form)
{
Win32.ReleaseCapture();
Win32.SendMessage(form.Handle, Win32.WM_NCLBUTTONDOWN, Win32.HTCAPTION, 0);
}
调用窗体移动函数:
View Code
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Left)
{
Render.MoveWindow(this);
}
}
三:窗体边框的绘制与边框阴影的实现
边框的绘制:边框的绘制使用用PS制作好的图片来进行贴图操作,在贴图的过程中使用九宫图贴图方法,保证此边框图片能满足任何大小的窗体。
窗体边框的实现:此部分主要涉及到对CS_DropSHADOW的了解,只要在窗口的ClassStyle添加此样式即可,关键代码如下:
View Code
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
if (!DesignMode)
{
cp.ClassStyle |= (int) ClassStyle.CS_DropSHADOW;
}
return cp;
}
}
对于无边框窗体圆角矩形的处理,我这里采用的是使用API函数CreateRoundRectRgn,相比于自己用GDI+写的处理圆角的函数,效果要稍微好点,至少线条在圆角处过渡的比较平滑,为了便于复用,我把其封装到窗体自绘辅助类RenderHlper的SetFormRoundRectRgn函数中:
View Code
/// <summary>
/// 设置窗体的圆角矩形
/// </summary>
/// <param name="form">需要设置的窗体</param>
/// <param name="rgnRadius">圆角矩形的半径</param>
public static void SetFormRoundRectRgn(Form form, int rgnRadius)
{
int hRgn = 0;
hRgn = Win32.CreateRoundRectRgn(0, 0, form.Width + 1, form.Height + 1, rgnRadius, rgnRadius);
Win32.SetWindowRgn(form.Handle, hRgn, true);
Win32.DeleteObject(hRgn);
}
此处需要把所需要的API函数引用到类Win32中,引用的时候注意添加 System.Runtime.InteropServices 命名空间:
View Code
[DllImport("gdi32.dll")]
public static extern int CreateRoundRectRgn(int x1, int y1, int x2, int y2, int x3, int y3);
[DllImport("user32.dll")]
public static extern int SetWindowRgn(IntPtr hwnd, int hRgn, Boolean bRedraw);
[DllImport("gdi32.dll", EntryPoint = "DeleteObject", CharSet = CharSet.Ansi)]
public static extern int DeleteObject(int hObject);
重写窗体的OnSizeChanged事件,并在此事件中调用SetFormRoundRectRgn,此处的Radius参数为定义的窗体圆角半径属性:
View Code
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
RenderHelper.SetFormRoundRectRgn(this, Radius);
}
二:无边框窗体大小的改变与移动
当把窗体的FormBorderStyle属性调整为FormBorderStyle.None时,此时,窗体的大小改变不了,同时窗体不能移动。要想实现无边框窗体大小的改变与移动,可采用如下方法:
(1)重写窗体的过程WndProc:
主要是对WM_NCHITTEST消息进行处理,根据事件的发生位置来进行不同方向箭头的调整,窗体大小改变与移动的函数:
View Code
//调整窗体大小
private void WmNcHitTest(ref Message m)
{
int wparam = m.LParam.ToInt32();
Point mouseLocation = new Point(RenderHelper.LOWORD(wparam),RenderHelper.HIWORD(wparam));
mouseLocation = PointToClient(mouseLocation);
if (WindowState != FormWindowState.Maximized )
{
if (CanResize == true)
{
if (mouseLocation.X < 5 && mouseLocation.Y < 5)
{
m.Result = new IntPtr(Win32.HTTOPLEFT);
return;
}
if (mouseLocation.X > Width - 5 && mouseLocation.Y < 5)
{
m.Result = new IntPtr(Win32.HTTOPRIGHT);
return;
}
if (mouseLocation.X < 5 && mouseLocation.Y > Height - 5)
{
m.Result = new IntPtr(Win32.HTBOTTOMLEFT);
return;
}
if (mouseLocation.X > Width - 5 && mouseLocation.Y > Height - 5)
{
m.Result = new IntPtr(Win32.HTBOTTOMRIGHT);
return;
}
if (mouseLocation.Y < 3)
{
m.Result = new IntPtr(Win32.HTTOP);
return;
}
if (mouseLocation.Y > Height - 3)
{
m.Result = new IntPtr(Win32.HTBOTTOM);
return;
}
if (mouseLocation.X < 3)
{
m.Result = new IntPtr(Win32.HTLEFT);
return;
}
if (mouseLocation.X > Width - 3)
{
m.Result = new IntPtr(Win32.HTRIGHT);
return;
}
}
}
m.Result = new IntPtr(Win32.HTCAPTION);
}
重写窗体过程:
View Code
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case Win32.WM_NCHITTEST:
WmNcHitTest(ref m);
break;
default:
base.WndProc(ref m);
break;
}
}
(2)对于仅仅只想实现窗体的移动而不改变窗体的大小,可以重写OnMouseDown事件中发送HTCAPTION消息来实现无边框窗体的移动,具体的实现代码如下:
View Code
/// <summary>
/// 移动窗体
/// </summary>
public static void MoveWindow(Form form)
{
Win32.ReleaseCapture();
Win32.SendMessage(form.Handle, Win32.WM_NCLBUTTONDOWN, Win32.HTCAPTION, 0);
}
调用窗体移动函数:
View Code
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Left)
{
Render.MoveWindow(this);
}
}
三:窗体边框的绘制与边框阴影的实现
边框的绘制:边框的绘制使用用PS制作好的图片来进行贴图操作,在贴图的过程中使用九宫图贴图方法,保证此边框图片能满足任何大小的窗体。
窗体边框的实现:此部分主要涉及到对CS_DropSHADOW的了解,只要在窗口的ClassStyle添加此样式即可,关键代码如下:
View Code
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
if (!DesignMode)
{
cp.ClassStyle |= (int) ClassStyle.CS_DropSHADOW;
}
return cp;
}
}
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询