C# 轻松实现对窗体(Form)换肤[转]
一直想写一个比较完整的、容易扩展的窗体换肤的方案,由于时间问题,都没去实现这个想法。现在有朋友提出需要,就把以前写的重新拿出来看了一篇,花了些时间,做出了现在的这个换肤的方案。实现的过程中遇到了不少问题,但还是解决了,虽然也许还有些缺陷,但也算是比较完善了。现在只实现了完全代码绘制的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的完整代码:
- 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绘制类,敬请大家关注。
C# 轻松实现对窗体(Form)换肤[转]的更多相关文章
- .NET vs2010中使用IrisSkin2.dll轻松实现winForm窗体换肤功能
IrisSkin2.dll是一款很不错的免费皮肤控件,利用它可以轻松的实现winForm窗体换肤! 网上很多朋友说在VS2010中不能使用IrisSkin2.dll,我这里提供一个取巧的办法. Iri ...
- C# Winform中窗体的美化—— 用IrisSkin轻松实现换肤功能
今天经前辈提醒才知道winform窗体还有美化工具,呵呵,不得不说,孤陋寡闻了.下面总结一下irisskin2的使用步骤和遇到的问题及解决办法. 1.网址:http://www.pc6.com/sof ...
- C#.NET vs2010中使用IrisSkin4.dll轻松实现WinForm窗体换肤功能
IrisSkin2.dll是一款很不错的免费皮肤控件,利用它可以轻松的实现WinForm窗体换肤 然而IrisSkin2.dll只能在.NET Faremwork 4.0以及之前的版本使用,所以要在V ...
- Winform- IrisSkin.dll轻松实现窗体换肤功能
IrisSkin2.dll是一款很不错的免费皮肤控件,利用它可以轻松的实现winForm窗体换肤 然而IrisSkin2.dll只能在.NET Faremwork 4.0以及之前的版本使用,所以要在V ...
- C# 实现对窗体(Form)换肤
http://www.csharpwin.com/csharpresource/2992.shtml 一直想写一个比较完整的.容易扩展的窗体换肤的方案,由于时间问题,都没去实现这个想法.现在有朋友提出 ...
- C#窗体换肤
Form1.cs using System;using System.Collections.Generic;using System.ComponentModel;using System.Data ...
- WPF换肤之五:创建漂亮的窗体
原文:WPF换肤之五:创建漂亮的窗体 换肤效果 经过了前面四章的讲解,我们终于知道了如何拖拉窗体使之改变大小,也知道了如何处理鼠标事件,同时,也知道了如何利用更好的编写方式来编写一个方便实用和维护的换 ...
- WPF换肤之二:可拉动的窗体
原文:WPF换肤之二:可拉动的窗体 让我们接着上一章: WPF换肤之一:创建圆角窗体 来继续. 在这一章,我主要是实现对圆角窗体的拖动,改变大小功能. 拖动自绘窗体的步骤 首先,通过上节的设计,我们知 ...
- WPF换肤之一:创建圆角窗体
原文:WPF换肤之一:创建圆角窗体 我们都期望自己的软件能够有一套看上去很吸引人眼球的外衣,使得别人看上去既专业又有美感.这个系列就带领着大家一步一步的讲解如何设计出一套自己的WPF的窗体皮肤,如果文 ...
随机推荐
- URAL 1994 The Emperor's plan
期望$dp$. $dp[i][j]$表示第$1$种人有$i$个,第$2$种人有$j$个的情况下,到达目标状态的期望值.初始化$dp[i][0]=i$. 枚举一下这个状态死多少人,取个$max$,最后$ ...
- Java多线程编程——生产者-消费者模式(1)
生产者-消费者模式在生活中非常常见.就拿我们去餐馆吃饭为例.我们会遇到以下两种情况: 1.厨师-客人 如下图所示,生产者.消费者直接进行交互. 生产者生产出产品后,通知消费者:消费者消费后,通知生产者 ...
- 【我要学python】函数的系统学习
我的短期目标:python+CTF reverse 一起加油! #1,函数介绍 1,功能性 函数目的 2,隐藏性 (封装) (避免写重复代码) 例: #round为保留小数的函数 a = 3.1415 ...
- ORACLE PL/SQL编程详解(转)
原帖地址:http://blog.csdn.net/chenjinping123/article/details/8737604 ORACLE PL/SQL编程详解 SQL语言只是访问.操作数据库的语 ...
- 密码嗅探工具dsniff
密码嗅探工具dsniff 网络大量的服务都使用密码方式对使用者身份进行认证.如果使用非加密的方式传输,一旦数据被截获,就容易被嗅探到.Kali Linux预置了一款专用的密码嗅探工具dsniff. ...
- Kali Linux缺少ifconfig命令
Kali Linux缺少ifconfig命令 ifconfig是配置和查看网络的基础命令.在某些Kali Linux版本中,可能会缺少ifconfig命令.这个时候,用户需要手动安装该命令.该命令 ...
- JS模拟PHP的sleep
function sleep(n) { var start = new Date().getTime(); while(true) { if(new Date().getTime() - start ...
- [NOIP2017]列队(线段树/裂点splay)
考虑n=1的做法,就是支持: 1.在线删一个数 2.在结尾加一个数 3.查询序列的第y个数 用线段树记录区间内被删元素的个数,可以通过线段树上二分快速得解,对于新增的数,用vector记录即可. 对于 ...
- HDU 5514 Frogs(容斥原理)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5514 [题目大意] m个石子围成一圈,标号为0~m-1,现在有n只青蛙,每只每次跳a[i]个石子, ...
- BSGS算法+逆元 POJ 2417 Discrete Logging
POJ 2417 Discrete Logging Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 4860 Accept ...