C#winform 实现 QQ2009游戏界面(2)

  大家看就知道窗体是没有边框和标题栏的,再看窗体的四个角,并不是圆的,而是像被切了一刀一样,看来没有办法用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

  

写到这里,其实基本的模型已经出来了,估计下面怎么写很多人都知道了,接着我们要实现的是主窗体了,明天待续。。。

写到今天的代码点此下载  下载

你可能感兴趣的:(WinForm)