一直想写一个比较完整的、容易扩展的窗体换肤的方案,由于时间问题,都没去实现这个想法。现在有朋友提出需要,就把以前写的重新拿出来看了一篇,花了些时间,做出了现在的这个换肤的方案。实现的过程中遇到了不少问题,但还是解决了,虽然也许还有些缺陷,但也算是比较完善了。现在只实现了完全代码绘制的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的完整代码:
[csharp] view plaincopy
class="dp-c" start="1">
- 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绘制类,敬请大家关注。