zoukankan      html  css  js  c++  java
  • 【转】C# 轻松实现对窗体(Form)换肤

    C# 轻松实现对窗体(Form)换肤

    2009-09-25  来自:CS 程序员之窗 
    • 摘要:C#实现对窗体(Form)换肤,实现漂亮的个性化窗体,通过继承SkinFormRenderer,可以轻松实现自己喜欢的各种窗体风格,换肤后的窗体与标准的Windows窗体保持一样的功能,如:拥有系统菜单,拖动改变窗体大小等。
       

    一直想写一个比较完整的、容易扩展的窗体换肤的方案,由于时间问题,都没去实现这个想法。现在有朋友提出需要,就把以前写的重新拿出来看了一篇,花了些时间,做出了现在的这个换肤的方案。实现的过程中遇到了不少问题,但还是解决了,虽然也许还有些缺陷,但也算是比较完善了。现在只实现了完全代码绘制的SkinFormProfessionalRenderer,接下来有时间会写一个SkinFormImageRenderer,实现只要做好图片就可以换肤。

    在这先里发一下牢骚,最近看到很多网站转载了截图控件那几篇文章,但是版权声明、作者信息都去掉了,说实话,心里很不爽,这些文章和代码都是我辛辛苦苦的花了不少时间写出来的,我也没有不允许转载,但是你转载的时候为什么还要把作者信息去掉呢,请你尊重一下作者的劳动好吗?发完牢骚,先来看一下窗体换肤后的效果吧。



    看完效果,来看看SkinForm的实现原理:

    1、  Form设置为无标题栏窗口。

    2、  为了使Form可以像标准的Windows窗体那样拥有系统菜单和拖动改变窗体大小,加入WS_THICKFRAMEWS_SYSMENU窗体样式。

    3、  处理相应得窗体消息,实现窗体的标准操作。

    4、  实现SkinFormRenderer,绘制窗体的标题栏、边框、按钮等。

     

    原理只做简单介绍,要详细说明,那得写很多东西了,介绍一下SkinForm中加入的几个属性的功能:

    1、  BorderWidth,设置或获取窗体的边框的宽度。

    2、  CanResize:设置或获取窗体是否可以改变大小。

    3、  CaptionFont:设置或获取窗体标题的字体。

    4、  CapntionHeight:设置或获取窗体标题栏的高度。

    5、  CloseBoxSize:设置或获取关闭按钮的大小。

    6、  MinimizeBoxSize:设置或获取最小化按钮的大小。

    7、  MaximizeBoxSize:设置或获取最大化(还原)按钮的大小。

    8、  ControlBoxOffset:设置或获取控制按钮的偏移。

    9、  ControlBoxSpace:设置或获取控制按钮的间距。

    10、 RoundStyle:设置或获取窗体的圆角样式。

    11、   Radius:设置或获取窗体的圆角的大小。

    12、   Renderer:设置或获取窗体的绘制方法。

    接下来介绍窗体的绘制类SkinFormRenderer,这是比较重要的类,它是一个抽象类,重写它里面的绘制方法,就可以得到新的窗体皮肤。这个类里面主要有几个抽象方法:

    1、  CreateRegion:创建一个Region,提供给SkinForm使用。

    2、  OnRenderSkinFormCaption:绘制窗体标题栏。

    3、  OnRenderSkinFormBorder:绘制窗体边框。

    4、  OnRenderSkinFormBackground:绘制窗体背景。

    5、  OnRenderSkinFormControlBox:绘制窗体控制按钮(最小化、最大化、关闭);

    看看SkinFormRenderer的完整代码:

    public abstract class SkinFormRenderer
    {
    #region Fields

    private EventHandlerList _events;

    private static readonly object EventRenderSkinFormCaption = new object();
    private static readonly object EventRenderSkinFormBorder = new object();
    private static readonly object EventRenderSkinFormBackground = new object();
    private static readonly object EventRenderSkinFormControlBox = new object();

    #endregion


    #region Constructors

    protected SkinFormRenderer()
    {
    }


    #endregion


    #region Properties

    protected EventHandlerList Events
    {
    get
    {
    if (_events == null)
    {
    _events
    = new EventHandlerList();
    }

    return _events;
    }

    }


    #endregion


    #region Events

    public event SkinFormCaptionRenderEventHandler RenderSkinFormCaption
    {
    add
    { AddHandler(EventRenderSkinFormCaption, value); }
    remove
    { RemoveHandler(EventRenderSkinFormCaption, value); }
    }


    public event SkinFormBorderRenderEventHandler RenderSkinFormBorder
    {
    add
    { AddHandler(EventRenderSkinFormBorder, value); }
    remove
    { RemoveHandler(EventRenderSkinFormBorder, value); }
    }


    public event SkinFormBackgroundRenderEventHandler RenderSkinFormBackground
    {
    add
    { AddHandler(EventRenderSkinFormBackground, value); }
    remove
    { RemoveHandler(EventRenderSkinFormBackground, value); }
    }


    public event SkinFormControlBoxRenderEventHandler RenderSkinFormControlBox
    {
    add
    { AddHandler(EventRenderSkinFormControlBox, value); }
    remove
    { RemoveHandler(EventRenderSkinFormControlBox, value); }
    }


    #endregion


    #region Public Methods

    public abstract Region CreateRegion(SkinForm form);

    public abstract void InitSkinForm(SkinForm form);

    public void DrawSkinFormCaption(
    SkinFormCaptionRenderEventArgs e)
    {
    OnRenderSkinFormCaption(e);
    SkinFormCaptionRenderEventHandler handle
    =
    Events[EventRenderSkinFormCaption]
    as SkinFormCaptionRenderEventHandler;
    if (handle != null)
    {
    handle(
    this, e);
    }

    }



    public void DrawSkinFormBorder(
    SkinFormBorderRenderEventArgs e)
    {
    OnRenderSkinFormBorder(e);
    SkinFormBorderRenderEventHandler handle
    =
    Events[EventRenderSkinFormBorder]
    as SkinFormBorderRenderEventHandler;
    if (handle != null)
    {
    handle(
    this, e);
    }

    }



    public void DrawSkinFormBackground(
    SkinFormBackgroundRenderEventArgs e)
    {
    OnRenderSkinFormBackground(e);
    SkinFormBackgroundRenderEventHandler handle
    =
    Events[EventRenderSkinFormBackground]
    as SkinFormBackgroundRenderEventHandler;
    if (handle != null)
    {
    handle(
    this, e);
    }

    }


    public void DrawSkinFormControlBox(
    SkinFormControlBoxRenderEventArgs e)
    {
    OnRenderSkinFormControlBox(e);
    SkinFormControlBoxRenderEventHandler handle
    =
    Events[EventRenderSkinFormControlBox]
    as SkinFormControlBoxRenderEventHandler;
    if (handle != null)
    {
    handle(
    this, e);
    }

    }


    #endregion


    #region Protected Render Methods

    protected abstract void OnRenderSkinFormCaption(
    SkinFormCaptionRenderEventArgs e);

    protected abstract void OnRenderSkinFormBorder(
    SkinFormBorderRenderEventArgs e);

    protected abstract void OnRenderSkinFormBackground(
    SkinFormBackgroundRenderEventArgs e);

    protected abstract void OnRenderSkinFormControlBox(
    SkinFormControlBoxRenderEventArgs e);

    #endregion


    #region Protected Methods

    [UIPermission(SecurityAction.Demand, Window
    = UIPermissionWindow.AllWindows)]
    protected void AddHandler(object key, Delegate value)
    {
    Events.AddHandler(key, value);
    }


    [UIPermission(SecurityAction.Demand, Window
    = UIPermissionWindow.AllWindows)]
    protected void RemoveHandler(object key, Delegate value)
    {
    Events.RemoveHandler(key, value);
    }


    #endregion

    }

    在项目中实现了SkinFormProfessionalRenderer类,这个类实现了类似QQ2008的窗体的绘制,效果就是文章开始那贴出来的图了。还有一些其他辅助功能的类就不一一介绍了,接下来有时间,我会实现一个SkinFormImageRenderer绘制类,敬请大家关注。

    声明:

    本文版权归作者和CS 程序员之窗所有,欢迎转载,转载必须保留以下版权信息,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

    作者:Starts_2000

    出处:CS 程序员之窗 http://www.csharpwin.com

    你可以免费使用或修改提供的源代码,但请保留源代码中的版权信息,详情请查看:

    CS程序员之窗开源协议 http://www.csharpwin.com/csol.html

    作者:Asion Tang
    凡是没有注明[转载]的文章,本Blog发表的文章版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    剑指 Offer 43. 1~n整数中1出现的次数
    剑指 Offer 54. 二叉搜索树的第k大节点(递归)
    第三个JSP作业
    第二个JSP作业-用循环结构输出三行五列的table
    第二个JSP作业-编写jsp页面,输出大写、小写英文字母表
    第一个JSP作业
    安卓课设
    第十次作业
    第八次作业
    第九次作业
  • 原文地址:https://www.cnblogs.com/AsionTang/p/1741475.html
Copyright © 2011-2022 走看看