大家看就知道窗体是没有边框和标题栏的,再看窗体的四个角,并不是圆的,而是像被切了一刀一样,看来没有办法用API的圆角函数了,只能考虑GDI的办法了,在GraphicsPath类中,有一个方法AddClosedCurve(Point[] points, float tension);,我们看MSDN上的解释(向此路径添加一个闭合曲线。由于曲线经过数组中的每个点,因此使用基数样条曲线。参数: tension: 介于 0 到 1 之间的一个值,它指定曲线在点与点之间弯曲的程度,0 表示最小弯曲(最锐拐角),1 表示最平滑弯曲。points:一个 System.Drawing.Point 结构的数组,它表示定义曲线的点。)有了这个,我的就可以实现了,因为每个窗体都是这样,所以我们只要把formbase处理一下,其它的就不用处理了。函数如下
private void ChangeRegion(Control control,int rg)
{
GraphicsPath oPath = new GraphicsPath();
oPath.AddClosedCurve(new Point[]
{
new Point(1, rg+1), //0
new Point(rg+1,1),//1
new Point(control.Width -rg-1, 1), //2
new Point(control.Width-1, rg+1), //3
new Point(control.Width-1, control.Height - rg-1-1),//4
new Point(control.Width - rg-1-1, control.Height-1), //5
new Point(rg+1, control.Height-1), //6
new Point(1, control.Height - rg-1)},//7
(float)0
);
oPath.CloseAllFigures();
control.Region = new Region(oPath);
}
这里我也不知道为什么会有点误差,如果按数学的写的话,不是这样子的,但是为了把四个角改成一样,所以对有些点进行了修改。以后再想想这里为什么会不对。
因为窗体可以拉大和缩小,所以要在OnSizeChanged中调用它。
对于重绘的窗体很容易引起窗体的闪烁,很要必要在构造函数中加入下面的代码:
public FormBase()
{
InitializeComponent();
this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
}
因为窗体打开时要加载图片作为皮肤,所以我们定义一个虚函数来加载这些图片,这样其它的各样窗体只要重写这个函数就可以了,定义如下:
public void PerformReSetFormBitmap()
{
try
{
ReSetFormBitmap();
}
catch
{
throw;
}
}
public virtual void ReSetFormBitmap()
{
}
然后在onload的时候调用它就可以了。
因为还有一个换肤的功能,所以加载了皮肤之后,如果不是默认皮肤我们要执行换肤,那么还要有一个肤的函数。又因为皮肤是由主窗体定义的,那么我们要定义一个主窗体,如果新打开的子窗和主窗体的不一致,我们将进行切换,所以我们先在shared类中定义一个mainform,所以,我要还要加一个mainform的接口,到时程序运行的时候我们就进行指定。新建一个IForms的文件夹,之后考虑我们要在接口中定义的方法了,QQ游戏界面的换肤有8种调色和9种底纹,那我们将这些定义enum,定义如下:
public enum SkinColor
{
Default,
草莓,
橘子,
青草,
灰蓝,
紫罗兰,
巧克力,
OFFICE,
Undefault
}
public enum BackgroundStripe
{
Default,
淡淡墨绿,
芙蓉轻粉,
荷叶嫩绿,
橘黄雪花,
清雅幽兰,
空灵淡蓝,
柔和雅灰,
腊梅飘香
}
这里的定义是根据QQ游戏界面来定义的。
下面我们可以定义上面说的接口了:
namespace CRD.WinUI.IForm
{
public interface IMainForm
{
void PerformChangeSkinColor(); //调色
void PerformChangeSkinColor(SkinColor skinColor);
void PerformChangeBackgroundStripe(BackgroundStripe backgroundStripe); //底纹
void PerformAllFormChangeSkinColor(SkinColor skinColor);
SkinColor CurrentSkinColor {get;set;}
}
}
现在可以来定义shard中的接口属性了:
public static class Shared
{
private static IMainForm _mainForm;
public static IMainForm MainForm
{
get { return _mainForm; }
set { _mainForm = value; }
}
}
因为还要知道当前使用的是什么皮肤,所以还要在shared中和formbase中都同时定义CurrentSkinColor才行,定义如下
formbase:
private SkinColor _currentSkinColor = SkinColor.Default;
public SkinColor CurrentSkinColor
{
get { return _currentSkinColor; }
set { _currentSkinColor = value; }
}
shared:
private static SkinColor _currentSkinColor = SkinColor.Default;
public static SkinColor CurrentSkinColor
{
get { return _currentSkinColor; }
set { _currentSkinColor = value; }
}
接着,我们应该定义函数来更改皮肤了,因为考虑到很多窗体中都要用到,我们将它定义在shard中
public static void ChangeSkinColor(SkinColor skinColor, Control control)
{
ChangeSkinColor(skinColor, control, false);
}
public static void ChangeSkinColor(SkinColor skinColor, Control control, bool Reset)
{
//这里如何写后面再写了
}
public static void ChangeControlsSkinColor(Control parentControl)
{
Shared.ChangeControlSkinColor(parentControl);
foreach (Control control in parentControl.Controls)
{
if (control.Controls.Count > 0)
{
ChangeControlsSkinColor(control);
}
else
{
Shared.ChangeControlSkinColor(control);
}
}
}
public static void ChangeControlSkinColor(Control control)
{
//这里才是得重要
}
public static void ChangeBackgroundStripe(BackgroundStripe backgroundStripe, Control control)
{
if (backgroundStripe != BackgroundStripe.Default)
{
switch (backgroundStripe)
{
case BackgroundStripe.淡淡墨绿:
break;
case BackgroundStripe.芙蓉轻粉:
ChangeSkinColor(SkinColor.草莓, control);
break;
case BackgroundStripe.荷叶嫩绿:
ChangeSkinColor(SkinColor.青草, control);
break;
case BackgroundStripe.橘黄雪花:
ChangeSkinColor(SkinColor.橘子, control);
break;
case BackgroundStripe.清雅幽兰:
break;
case BackgroundStripe.空灵淡蓝:
ChangeSkinColor(SkinColor.灰蓝, control);
break;
case BackgroundStripe.柔和雅灰:
break;
case BackgroundStripe.腊梅飘香:
ChangeSkinColor(SkinColor.OFFICE, control);
break;
default:
break;
}
}
Shared.MainForm.CurrentSkinColor = Shared.CurrentSkinColor;
}
这回我们可以回到formbase中了,那么它的onload应该是这样的了:
protected override void OnLoad(EventArgs e)
{
if (!DesignMode)
{
PerformReSetFormBitmap();
}
base.OnLoad(e);
if (!DesignMode)
{
if (this != Shared.MainForm && this.CurrentSkinColor != Shared.CurrentSkinColor)
{
Shared.ChangeSkinColor(Shared.CurrentSkinColor, this, true);
}
ChangeRegion(this, 4);
}
}
为了实现窗体换肤统一,即主窗体换了,子窗体也要换,我们还要在窗体上定义函数来调用,定义如下
#region ChangeSkinColor
public void PerformChangeSkinColor()
{
PerformChangeSkinColor(SkinColor.Undefault);
}
public void PerformChangeSkinColor(SkinColor skinColor)
{
try
{
ChangeSkinColor(skinColor);
}
catch
{
throw;
}
finally
{
}
}
public virtual void ChangeSkinColor(SkinColor skinColor)
{
if (this.CurrentSkinColor != skinColor)
{
this.ReSetFormBitmap();
if (skinColor != SkinColor.Undefault)
{
Shared.ChangeSkinColor(skinColor, this);
}
}
else
{
this.ReSetFormBitmap();
Shared.ChangeControlsSkinColor(this);
}
this.CurrentSkinColor = Shared.CurrentSkinColor;
}
#endregion
写到这里,其实基本的模型已经出来了,估计下面怎么写很多人都知道了,接着我们要实现的是主窗体了,明天待续。。。
写到今天的代码点此下载 下载