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

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

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

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

2、  为了使Form可以像标准的Windows窗体那样拥有系统菜单和拖动改变窗体大小,加入WS_THICKFRAME和WS_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的完整代码:

  1. public abstract class SkinFormRenderer
  2. {
  3. #region Fields
  4. private EventHandlerList _events;
  5. private static readonly object EventRenderSkinFormCaption = new object();
  6. private static readonly object EventRenderSkinFormBorder = new object();
  7. private static readonly object EventRenderSkinFormBackground = new object();
  8. private static readonly object EventRenderSkinFormControlBox = new object();
  9. #endregion
  10. #region Constructors
  11. protected SkinFormRenderer()
  12. {
  13. }
  14. #endregion
  15. #region Properties
  16. protected EventHandlerList Events
  17. {
  18. get
  19. {
  20. if (_events == null)
  21. {
  22. _events = new EventHandlerList();
  23. }
  24. return _events;
  25. }
  26. }
  27. #endregion
  28. #region Events
  29. public event SkinFormCaptionRenderEventHandler RenderSkinFormCaption
  30. {
  31. add { AddHandler(EventRenderSkinFormCaption, value); }
  32. remove { RemoveHandler(EventRenderSkinFormCaption, value); }
  33. }
  34. public event SkinFormBorderRenderEventHandler RenderSkinFormBorder
  35. {
  36. add { AddHandler(EventRenderSkinFormBorder, value); }
  37. remove { RemoveHandler(EventRenderSkinFormBorder, value); }
  38. }
  39. public event SkinFormBackgroundRenderEventHandler RenderSkinFormBackground
  40. {
  41. add { AddHandler(EventRenderSkinFormBackground, value); }
  42. remove { RemoveHandler(EventRenderSkinFormBackground, value); }
  43. }
  44. public event SkinFormControlBoxRenderEventHandler RenderSkinFormControlBox
  45. {
  46. add { AddHandler(EventRenderSkinFormControlBox, value); }
  47. remove { RemoveHandler(EventRenderSkinFormControlBox, value); }
  48. }
  49. #endregion
  50. #region Public Methods
  51. public abstract Region CreateRegion(SkinForm form);
  52. public abstract void InitSkinForm(SkinForm  form);
  53. public void DrawSkinFormCaption(
  54. SkinFormCaptionRenderEventArgs e)
  55. {
  56. OnRenderSkinFormCaption(e);
  57. SkinFormCaptionRenderEventHandler handle =
  58. Events[EventRenderSkinFormCaption]
  59. as SkinFormCaptionRenderEventHandler;
  60. if (handle != null)
  61. {
  62. handle(this, e);
  63. }
  64. }
  65. public void DrawSkinFormBorder(
  66. SkinFormBorderRenderEventArgs e)
  67. {
  68. OnRenderSkinFormBorder(e);
  69. SkinFormBorderRenderEventHandler handle =
  70. Events[EventRenderSkinFormBorder]
  71. as SkinFormBorderRenderEventHandler;
  72. if (handle != null)
  73. {
  74. handle(this, e);
  75. }
  76. }
  77. public void DrawSkinFormBackground(
  78. SkinFormBackgroundRenderEventArgs e)
  79. {
  80. OnRenderSkinFormBackground(e);
  81. SkinFormBackgroundRenderEventHandler handle =
  82. Events[EventRenderSkinFormBackground]
  83. as SkinFormBackgroundRenderEventHandler;
  84. if (handle != null)
  85. {
  86. handle(this, e);
  87. }
  88. }
  89. public void DrawSkinFormControlBox(
  90. SkinFormControlBoxRenderEventArgs e)
  91. {
  92. OnRenderSkinFormControlBox(e);
  93. SkinFormControlBoxRenderEventHandler handle =
  94. Events[EventRenderSkinFormControlBox]
  95. as SkinFormControlBoxRenderEventHandler;
  96. if (handle != null)
  97. {
  98. handle(this, e);
  99. }
  100. }
  101. #endregion
  102. #region Protected Render Methods
  103. protected abstract void OnRenderSkinFormCaption(
  104. SkinFormCaptionRenderEventArgs e);
  105. protected abstract void OnRenderSkinFormBorder(
  106. SkinFormBorderRenderEventArgs e);
  107. protected abstract void OnRenderSkinFormBackground(
  108. SkinFormBackgroundRenderEventArgs e);
  109. protected abstract void OnRenderSkinFormControlBox(
  110. SkinFormControlBoxRenderEventArgs e);
  111. #endregion
  112. #region Protected Methods
  113. [UIPermission(SecurityAction.Demand, Window = UIPermissionWindow.AllWindows)]
  114. protected void AddHandler(object key, Delegate value)
  115. {
  116. Events.AddHandler(key, value);
  117. }
  118. [UIPermission(SecurityAction.Demand, Window = UIPermissionWindow.AllWindows)]
  119. protected void RemoveHandler(object key, Delegate value)
  120. {
  121. Events.RemoveHandler(key, value);
  122. }
  123. #endregion
  124. }

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

C# 轻松实现对窗体(Form)换肤[转]的更多相关文章

  1. .NET vs2010中使用IrisSkin2.dll轻松实现winForm窗体换肤功能

    IrisSkin2.dll是一款很不错的免费皮肤控件,利用它可以轻松的实现winForm窗体换肤! 网上很多朋友说在VS2010中不能使用IrisSkin2.dll,我这里提供一个取巧的办法. Iri ...

  2. C# Winform中窗体的美化—— 用IrisSkin轻松实现换肤功能

    今天经前辈提醒才知道winform窗体还有美化工具,呵呵,不得不说,孤陋寡闻了.下面总结一下irisskin2的使用步骤和遇到的问题及解决办法. 1.网址:http://www.pc6.com/sof ...

  3. C#.NET vs2010中使用IrisSkin4.dll轻松实现WinForm窗体换肤功能

    IrisSkin2.dll是一款很不错的免费皮肤控件,利用它可以轻松的实现WinForm窗体换肤 然而IrisSkin2.dll只能在.NET Faremwork 4.0以及之前的版本使用,所以要在V ...

  4. Winform- IrisSkin.dll轻松实现窗体换肤功能

    IrisSkin2.dll是一款很不错的免费皮肤控件,利用它可以轻松的实现winForm窗体换肤 然而IrisSkin2.dll只能在.NET Faremwork 4.0以及之前的版本使用,所以要在V ...

  5. C# 实现对窗体(Form)换肤

    http://www.csharpwin.com/csharpresource/2992.shtml 一直想写一个比较完整的.容易扩展的窗体换肤的方案,由于时间问题,都没去实现这个想法.现在有朋友提出 ...

  6. C#窗体换肤

    Form1.cs using System;using System.Collections.Generic;using System.ComponentModel;using System.Data ...

  7. WPF换肤之五:创建漂亮的窗体

    原文:WPF换肤之五:创建漂亮的窗体 换肤效果 经过了前面四章的讲解,我们终于知道了如何拖拉窗体使之改变大小,也知道了如何处理鼠标事件,同时,也知道了如何利用更好的编写方式来编写一个方便实用和维护的换 ...

  8. WPF换肤之二:可拉动的窗体

    原文:WPF换肤之二:可拉动的窗体 让我们接着上一章: WPF换肤之一:创建圆角窗体 来继续. 在这一章,我主要是实现对圆角窗体的拖动,改变大小功能. 拖动自绘窗体的步骤 首先,通过上节的设计,我们知 ...

  9. WPF换肤之一:创建圆角窗体

    原文:WPF换肤之一:创建圆角窗体 我们都期望自己的软件能够有一套看上去很吸引人眼球的外衣,使得别人看上去既专业又有美感.这个系列就带领着大家一步一步的讲解如何设计出一套自己的WPF的窗体皮肤,如果文 ...

随机推荐

  1. Saltstack 介绍、安装、配置语法(一)

    Slatstack 介绍 官网:https://saltstack.com/ 官方源:http://repo.saltstack.com/  (介绍各操作系统安装方法) yum install htt ...

  2. thinkphp5.0 多层MVC

    ThinkPHP基于MVC(Model-View-Controller,模型-视图-控制器)模式,并且均支持多层(multi-Layer)设计. 模型(Model)层 默认的模型层由Model类构成, ...

  3. RecyclerView悬浮标题

    效果图:        1.顶部会悬浮章的部分 2.第二章上滑会推挤第一章 3.第二章下拉会带出第一章 4.并不是所有时候都有悬浮部分(为什么这条标红,因为市面上几乎所有的悬浮都是必须存在且在顶部,害 ...

  4. JAVA编程思想读书笔记(三)--RTTI

    接上篇JAVA编程思想读书笔记(二) 第十一章 运行期类型判定 No1: 对于作为程序一部分的每个类,它们都有一个Class对象.换言之,每次写一个新类时,同时也会创建一个Class对象(更恰当的说, ...

  5. 【JAVAWEB学习笔记】22_ajax:异步校验用户名和站内查询

    Js原生Ajax和Jquery的Ajax 学习目标 案例1-异步校验用户名是否存在 案例2-站内查询 一.Ajax概述 1.什么是同步,什么是异步 同步现象:客户端发送请求到服务器端,当服务器返回响应 ...

  6. Unity 2D游戏开发教程之精灵的死亡和重生

    Unity 2D游戏开发教程之精灵的死亡和重生 精灵的死亡和重生 目前为止,游戏项目里的精灵只有Idle和Walking这两种状态.也就是说,无论精灵在游戏里做什么,它都不会进入其它的状态,如死亡.于 ...

  7. HDU 2222 Keywords Search 【AC自动机】

    题目链接:[http://acm.hdu.edu.cn/showproblem.php?pid=2222] 题意:给出很多小字符串,然后给出一个文本串,问文本串中包含多少个小字符串.也就是说如果文本串 ...

  8. [BZOJ2431][HAOI2009]逆序对数列(DP)

    从小到大加数,根据加入的位置转移,裸的背包DP. #include<cstdio> #include<cstring> #include<algorithm> #d ...

  9. [BZOJ 2821] 作诗

    Link: BZOJ 2821 传送门 Solution: 一道类似区间众数的经典分块 由于个数为偶数这样的条件不能支持快速合并 因此要先$O(n*sqrt(n))$预处理出$pre[i][j]$表示 ...

  10. sklearn中的投票法

    投票法(voting)是集成学习里面针对分类问题的一种结合策略.基本思想是选择所有机器学习算法当中输出最多的那个类. 分类的机器学习算法输出有两种类型:一种是直接输出类标签,另外一种是输出类概率,使用 ...