首页 > 代码库 > 自己画WinForm 皮肤包括默认控件

自己画WinForm 皮肤包括默认控件

好久没来博客园,今天捣鼓到现在就是为了把之前的皮肤控件完善好,

之前也看了很多技术文章,大多数都是自己重写系统控件实现换肤,几乎没有像东日的(IrisSkin)控件一样 添加一个组件 把系统的皮肤全换掉,我曾经也是重写系统的控件,但我就喜欢瞎捣鼓,于是就开始找这方面的资料,苦于没学过底层,对windows窗口 以及消息循环机制不了解,找资料也基本上白搭了许久,但最后以为自己能想到的最笨的方法实现 了继承了自己写的父窗口,那么窗口添加的控件就是自己画的 而不是系统画的,

先上传一张效果图:

 

 

整天效果应该也还算勉强吧,目前我也就写了这几个控件的美化,虽然这破代码捣鼓好几天了,但代码依旧混乱不堪,加上反编译了微软的部分东西,因为想尽快出来,代码都没看,直接复制过来修改成编译不报错就完事了,

 

现在我来说说我实现的思路:

前题条件继承的是自己写的FormBase
然后重写了系统的OnControlAdded 方法,在这里为每个控件添加美化的类,

可怎么添加了? 找了好久,找到了一个可拦截Control消息的接口:IWindowTarget 接口(具体请参考 MSDN 微软不建议直接使用的一个类)

Control 公开并允许修改这个接口的信息,

IWindowTarget 接口有两个方法,一个是更换控件句柄的(也许应该叫设置控件句柄) 还有一个就是处理 Windows 消息的OnMessage
 我要做的就是拦截Windows 消息的重画消息,拦截下来 然后自己画,其它的还是丢个控件处理,(后来发现貌似实现IMessageFilter接口也可以实现)

好了屁话不多说了 上代码 上demo 没写完  希望大神能帮忙完善下就最好了-.-!

对了 就是问个2B问题,怎么拦截所有的Form创建或者Form创建句柄时?我用IMessageFilter好像拦截不到,

唉 代码有点乱,各位将就着看吧

部分代码:

using DotNet.Windows.Forms.Internal;using System;using System.Drawing;using System.Drawing.Drawing2D;using System.Drawing.Imaging;using System.Reflection;using System.Runtime.InteropServices;using System.Windows.Forms;namespace DotNet.Windows.Forms{    public abstract class WindowTarget<T> : IWindowTarget        where T : Control    {        private static readonly ControlStyles UserControlStyles;        private static readonly MethodInfo SetStyleMethod;        private static readonly MethodInfo SetStateMethod;        private static readonly PropertyInfo CacheTextInternalProperty;        private static readonly FieldInfo windowField;        static WindowTarget()        {            UserControlStyles = ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.Selectable | ControlStyles.ContainerControl | ControlStyles.UserPaint;            SetStyleMethod = typeof(Control).GetMethod("SetStyle",BindingFlags.Instance |BindingFlags.NonPublic);            SetStateMethod = typeof(Control).GetMethod("SetState", BindingFlags.Instance | BindingFlags.NonPublic);            windowField = typeof(Control).GetField("window", BindingFlags.Instance | BindingFlags.NonPublic);            CacheTextInternalProperty = typeof(Control).GetProperty("CacheTextInternal", BindingFlags.Instance | BindingFlags.NonPublic);        }        private T m_Control;        private IWindowTarget m_WindowTarget;        private MouseState m_MouseState = MouseState.Normal;        protected WindowTarget(T control)        {            m_Control = control;            m_WindowTarget = m_Control.WindowTarget;            m_Control.MouseUp += (o, e) => { this.MouseState = MouseState.Up; };            m_Control.MouseEnter += (o, e) => { this.MouseState = MouseState.Move; };            m_Control.MouseLeave += (o, e) => { this.MouseState = MouseState.Leave; };            m_Control.MouseDown += (o, e) => { this.MouseState = MouseState.Down; };        }        protected virtual void SetStyle(ControlStyles styles, bool value)        {            SetStyleMethod.Invoke(Control, new object[] { styles, value });        }        private object window        {            get            {                return windowField.GetValue(Control);            }        }        private bool CacheTextInternal        {            get            {                return (bool)CacheTextInternalProperty.GetValue(Control, null);            }            set            {                CacheTextInternalProperty.SetValue(Control, value, null);            }        }        protected virtual void SetState(int flag, bool value)        {            SetStyleMethod.Invoke(Control, new object[] { flag, value });        }        protected T Control { get { return m_Control; } }        protected IWindowTarget Target { get { return m_WindowTarget; } }        protected abstract void OnPaint(DotNet.Windows.Forms.Internal.PaintEventArgs e);        protected MouseState MouseState        {            get            {                return m_MouseState;            }            set            {                if (m_MouseState != value)                {                    m_MouseState = value;                    Control.Invalidate();                }            }        }        protected virtual Image GetImage()        {            switch (MouseState)            {                case MouseState.Leave:                case MouseState.Normal:                    return GetNormalImage();                case MouseState.Up:                case MouseState.Move:                    return GetMoveImage();                case MouseState.Down:                    return GetDownImage();                default:                    return null;            }        }        protected abstract Image GetNormalImage();        protected abstract Image GetMoveImage();        protected abstract Image GetDownImage();        protected void RendererBackground(Graphics g, Rectangle rect, Image backgroundImage, bool method)        {            if (!method)            {                g.DrawImage(backgroundImage, new Rectangle(rect.X + 0, rect.Y, 5, rect.Height), 0, 0, 5, backgroundImage.Height, GraphicsUnit.Pixel);                g.DrawImage(backgroundImage, new Rectangle(rect.X + 5, rect.Y, rect.Width - 10, rect.Height), 5, 0, backgroundImage.Width - 10, backgroundImage.Height, GraphicsUnit.Pixel);                g.DrawImage(backgroundImage, new Rectangle(rect.X + rect.Width - 5, rect.Y, 5, rect.Height), backgroundImage.Width - 5, 0, 5, backgroundImage.Height, GraphicsUnit.Pixel);            }            else            {                RendererBackground(g, rect, 5, backgroundImage);            }        }        /// <summary>        /// 渲染背景图片,使背景图片不失真        /// </summary>        /// <param name="g"></param>        /// <param name="rect"></param>        /// <param name="cut"></param>        /// <param name="backgroundImage"></param>        protected void RendererBackground(Graphics g, Rectangle rect, int cut, Image backgroundImage)        {            //左上角            g.DrawImage(backgroundImage, new Rectangle(rect.X, rect.Y, cut, cut), 0, 0, cut, cut, GraphicsUnit.Pixel);            //上边            g.DrawImage(backgroundImage, new Rectangle(rect.X + cut, rect.Y, rect.Width - cut * 2, cut), cut, 0, backgroundImage.Width - cut * 2, cut, GraphicsUnit.Pixel);            //右上角            g.DrawImage(backgroundImage, new Rectangle(rect.X + rect.Width - cut, rect.Y, cut, cut), backgroundImage.Width - cut, 0, cut, cut, GraphicsUnit.Pixel);            //左边            g.DrawImage(backgroundImage, new Rectangle(rect.X, rect.Y + cut, cut, rect.Height - cut * 2), 0, cut, cut, backgroundImage.Height - cut * 2, GraphicsUnit.Pixel);            //左下角            g.DrawImage(backgroundImage, new Rectangle(rect.X, rect.Y + rect.Height - cut, cut, cut), 0, backgroundImage.Height - cut, cut, cut, GraphicsUnit.Pixel);            //右边            g.DrawImage(backgroundImage, new Rectangle(rect.X + rect.Width - cut, rect.Y + cut, cut, rect.Height - cut * 2), backgroundImage.Width - cut, cut, cut, backgroundImage.Height - cut * 2, GraphicsUnit.Pixel);            //右下角            g.DrawImage(backgroundImage, new Rectangle(rect.X + rect.Width - cut, rect.Y + rect.Height - cut, cut, cut), backgroundImage.Width - cut, backgroundImage.Height - cut, cut, cut, GraphicsUnit.Pixel);            //下边            g.DrawImage(backgroundImage, new Rectangle(rect.X + cut, rect.Y + rect.Height - cut, rect.Width - cut * 2, cut), cut, backgroundImage.Height - cut, backgroundImage.Width - cut * 2, cut, GraphicsUnit.Pixel);            //平铺中间            g.DrawImage(backgroundImage, new Rectangle(rect.X + cut, rect.Y + cut, rect.Width - cut * 2, rect.Height - cut * 2), cut, cut, backgroundImage.Width - cut * 2, backgroundImage.Height - cut * 2, GraphicsUnit.Pixel);        }        #region IWindowTarget 成员        void IWindowTarget.OnHandleChange(IntPtr newHandle)        {            Target.OnHandleChange(newHandle);        }        private BufferedGraphicsContext BufferContext        {            get            {                return BufferedGraphicsManager.Current;            }        }        internal static IntPtr SetUpPalette(IntPtr dc, bool force, bool realizePalette)        {            IntPtr halftonePalette = Graphics.GetHalftonePalette();            IntPtr ptr2 = SafeNativeMethods.SelectPalette(new HandleRef(null, dc), new HandleRef(null, halftonePalette), force ? 0 : 1);            if ((ptr2 != IntPtr.Zero) && realizePalette)            {                SafeNativeMethods.RealizePalette(new HandleRef(null, dc));            }            return ptr2;        }        private void WmPaint(ref  Message m)        {            bool flag = true;            IntPtr zero = IntPtr.Zero;            NativeMethods.PAINTSTRUCT lpPaint = new NativeMethods.PAINTSTRUCT();            bool flag2 = false;            try            {                IntPtr wParam;                Rectangle clientRectangle;                if (m.WParam == IntPtr.Zero)                {                    zero = Control.Handle;                    wParam = UnsafeNativeMethods.BeginPaint(new HandleRef(this, zero), ref lpPaint);                    flag2 = true;                    clientRectangle = new Rectangle(lpPaint.rcPaint_left, lpPaint.rcPaint_top, lpPaint.rcPaint_right - lpPaint.rcPaint_left, lpPaint.rcPaint_bottom - lpPaint.rcPaint_top);                }                else                {                    wParam = m.WParam;                    clientRectangle = Control.ClientRectangle;                }                if (!flag || ((clientRectangle.Width > 0) && (clientRectangle.Height > 0)))                {                    IntPtr handle = IntPtr.Zero;                    BufferedGraphics graphics = null;                    DotNet.Windows.Forms.Internal.PaintEventArgs e = null;                    System.Drawing.Drawing2D.GraphicsState gstate = null;                    try                    {                        if (flag || (m.WParam == IntPtr.Zero))                        {                            handle = SetUpPalette(wParam, false, false);                        }                        if (flag)                        {                            try                            {                                graphics = this.BufferContext.Allocate(wParam, Control.ClientRectangle);                            }                            catch (Exception exception)                            {                                if (ClientUtils.IsCriticalException(exception))                                {                                    throw;                                }                                flag = false;                            }                        }                        if (graphics != null)                        {                            graphics.Graphics.SetClip(clientRectangle);                            e = new DotNet.Windows.Forms.Internal.PaintEventArgs(graphics.Graphics, clientRectangle);                            gstate = e.Graphics.Save();                        }                        else                        {                            e = new DotNet.Windows.Forms.Internal.PaintEventArgs(wParam, clientRectangle);                        }                        using (e)                        {                            try                            {                                if (((m.WParam == IntPtr.Zero) && true) || flag)                                {                                    this.PaintWithErrorHandling(e, 1);                                }                            }                            finally                            {                                if (gstate != null)                                {                                    e.Graphics.Restore(gstate);                                }                                else                                {                                    e.ResetGraphics();                                }                            }                            this.PaintWithErrorHandling(e, 2);                            if (graphics != null)                            {                                graphics.Render();                            }                        }                    }                    finally                    {                        if (handle != IntPtr.Zero)                        {                            SafeNativeMethods.SelectPalette(new HandleRef(null, wParam), new HandleRef(null, handle), 0);                        }                        if (graphics != null)                        {                            graphics.Dispose();                        }                    }                }            }            finally            {                if (flag2)                {                    UnsafeNativeMethods.EndPaint(new HandleRef(this, zero), ref lpPaint);                }            }        }        protected virtual void OnPaintBackground(DotNet.Windows.Forms.Internal.PaintEventArgs pevent)        {            NativeMethods.RECT rect = new NativeMethods.RECT();            UnsafeNativeMethods.GetClientRect(new HandleRef(this.window, Control.Handle), ref rect);            this.PaintBackground(pevent, new Rectangle(rect.left, rect.top, rect.right, rect.bottom));        }        internal void PaintBackground(DotNet.Windows.Forms.Internal.PaintEventArgs e, Rectangle rectangle)        {            this.PaintBackground(e, rectangle, Control.BackColor, Point.Empty);        }        internal void PaintBackground(DotNet.Windows.Forms.Internal.PaintEventArgs e, Rectangle rectangle, System.Drawing.Color backColor)        {            this.PaintBackground(e, rectangle, backColor, Point.Empty);        }        private bool RenderColorTransparent(System.Drawing.Color c)        {            return ((c.A < 0xff));        }        internal void PaintTransparentBackground(DotNet.Windows.Forms.Internal.PaintEventArgs e, Rectangle rectangle)        {            this.PaintTransparentBackground(e, rectangle, null);        }        internal static bool IsImageTransparent(Image backgroundImage)        {            return ((backgroundImage != null) && ((backgroundImage.Flags & 2) > 0));        }        internal static Rectangle CalculateBackgroundImageRectangle(Rectangle bounds, Image backgroundImage, ImageLayout imageLayout)        {            Rectangle rectangle = bounds;            if (backgroundImage != null)            {                switch (imageLayout)                {                    case ImageLayout.None:                        rectangle.Size = backgroundImage.Size;                        return rectangle;                    case ImageLayout.Tile:                        return rectangle;                    case ImageLayout.Center:                        {                            rectangle.Size = backgroundImage.Size;                            Size size = bounds.Size;                            if (size.Width > rectangle.Width)                            {                                rectangle.X = (size.Width - rectangle.Width) / 2;                            }                            if (size.Height > rectangle.Height)                            {                                rectangle.Y = (size.Height - rectangle.Height) / 2;                            }                            return rectangle;                        }                    case ImageLayout.Stretch:                        rectangle.Size = bounds.Size;                        return rectangle;                    case ImageLayout.Zoom:                        {                            Size size2 = backgroundImage.Size;                            float num = ((float)bounds.Width) / ((float)size2.Width);                            float num2 = ((float)bounds.Height) / ((float)size2.Height);                            if (num >= num2)                            {                                rectangle.Height = bounds.Height;                                rectangle.Width = (int)((size2.Width * num2) + 0.5);                                if (bounds.X >= 0)                                {                                    rectangle.X = (bounds.Width - rectangle.Width) / 2;                                }                                return rectangle;                            }                            rectangle.Width = bounds.Width;                            rectangle.Height = (int)((size2.Height * num) + 0.5);                            if (bounds.Y >= 0)                            {                                rectangle.Y = (bounds.Height - rectangle.Height) / 2;                            }                            return rectangle;                        }                }            }            return rectangle;        }        internal static void DrawBackgroundImage(Graphics g, Image backgroundImage, Color backColor, ImageLayout backgroundImageLayout, Rectangle bounds, Rectangle clipRect, Point scrollOffset, RightToLeft rightToLeft)        {            if (g == null)            {                throw new ArgumentNullException("g");            }            if (backgroundImageLayout == ImageLayout.Tile)            {                using (TextureBrush brush = new TextureBrush(backgroundImage, WrapMode.Tile))                {                    if (scrollOffset != Point.Empty)                    {                        Matrix transform = brush.Transform;                        transform.Translate((float)scrollOffset.X, (float)scrollOffset.Y);                        brush.Transform = transform;                    }                    g.FillRectangle(brush, clipRect);                    return;                }            }            Rectangle rect = CalculateBackgroundImageRectangle(bounds, backgroundImage, backgroundImageLayout);            if ((rightToLeft == RightToLeft.Yes) && (backgroundImageLayout == ImageLayout.None))            {                rect.X += clipRect.Width - rect.Width;            }            using (SolidBrush brush2 = new SolidBrush(backColor))            {                g.FillRectangle(brush2, clipRect);            }            if (!clipRect.Contains(rect))            {                if ((backgroundImageLayout == ImageLayout.Stretch) || (backgroundImageLayout == ImageLayout.Zoom))                {                    rect.Intersect(clipRect);                    g.DrawImage(backgroundImage, rect);                }                else if (backgroundImageLayout == ImageLayout.None)                {                    rect.Offset(clipRect.Location);                    Rectangle destRect = rect;                    destRect.Intersect(clipRect);                    Rectangle rectangle3 = new Rectangle(Point.Empty, destRect.Size);                    g.DrawImage(backgroundImage, destRect, rectangle3.X, rectangle3.Y, rectangle3.Width, rectangle3.Height, GraphicsUnit.Pixel);                }                else                {                    Rectangle rectangle4 = rect;                    rectangle4.Intersect(clipRect);                    Rectangle rectangle5 = new Rectangle(new Point(rectangle4.X - rect.X, rectangle4.Y - rect.Y), rectangle4.Size);                    g.DrawImage(backgroundImage, rectangle4, rectangle5.X, rectangle5.Y, rectangle5.Width, rectangle5.Height, GraphicsUnit.Pixel);                }            }            else            {                ImageAttributes imageAttr = new ImageAttributes();                imageAttr.SetWrapMode(WrapMode.TileFlipXY);                g.DrawImage(backgroundImage, rect, 0, 0, backgroundImage.Width, backgroundImage.Height, GraphicsUnit.Pixel, imageAttr);                imageAttr.Dispose();            }        }        internal void PaintTransparentBackground(DotNet.Windows.Forms.Internal.PaintEventArgs e, Rectangle rectangle, System.Drawing.Region transparentRegion)        {            Graphics g = e.Graphics;            Control parentInternal = Control.Parent;            if (parentInternal != null)            {                if (Application.RenderWithVisualStyles) // parentInternal.RenderTransparencyWithVisualStyles)                {                    System.Drawing.Drawing2D.GraphicsState gstate = null;                    if (transparentRegion != null)                    {                        gstate = g.Save();                    }                    try                    {                        if (transparentRegion != null)                        {                            g.Clip = transparentRegion;                        }                        ButtonRenderer.DrawParentBackground(g, rectangle, Control);                        return;                    }                    finally                    {                        if (gstate != null)                        {                            g.Restore(gstate);                        }                    }                }                Rectangle rectangle2 = new Rectangle(-Control.Left, -Control.Top, parentInternal.Width, parentInternal.Height);                Rectangle clipRect = new Rectangle(rectangle.Left + Control.Left, rectangle.Top + Control.Top, rectangle.Width, rectangle.Height);                using (WindowsGraphics graphics2 = WindowsGraphics.FromGraphics(g))                {                    graphics2.DeviceContext.TranslateTransform(-Control.Left, -Control.Top);                    using (DotNet.Windows.Forms.Internal.PaintEventArgs args = new DotNet.Windows.Forms.Internal.PaintEventArgs(graphics2.GetHdc(), clipRect))                    {                        if (transparentRegion != null)                        {                            args.Graphics.Clip = transparentRegion;                            args.Graphics.TranslateClip(-rectangle2.X, -rectangle2.Y);                        }                        try                        {                            //this.InvokePaintBackground(parentInternal, args);                            //this.InvokePaint(parentInternal, args);                        }                        finally                        {                            if (transparentRegion != null)                            {                                args.Graphics.TranslateClip(rectangle2.X, rectangle2.Y);                            }                        }                    }                    return;                }            }            g.FillRectangle(SystemBrushes.Control, rectangle);        }        internal void PaintBackground(DotNet.Windows.Forms.Internal.PaintEventArgs e, Rectangle rectangle, System.Drawing.Color backColor, Point scrollOffset)        {            backColor = Color.Transparent;            //ControlStyles.SupportsTransparentBackColor;            this.PaintTransparentBackground(e, rectangle);            //if (this.RenderColorTransparent(backColor))            //{            //    this.PaintTransparentBackground(e, rectangle);            //}            bool flag = ((Control is FormBase) || (this is MdiClient)) && Control.IsMirrored;            if (((Control.BackgroundImage != null) && !SystemInformation.HighContrast) && !flag)            {                if ((Control.BackgroundImageLayout == ImageLayout.Tile) && IsImageTransparent(Control.BackgroundImage))                {                    PaintTransparentBackground(e, rectangle);                }                Point autoScrollPosition = scrollOffset;                if ((Control is ScrollableControl) && (autoScrollPosition != Point.Empty))                {                    autoScrollPosition = ((ScrollableControl)(Control)Control).AutoScrollPosition;                }                if (IsImageTransparent(Control.BackgroundImage))                {                    PaintBackColor(e, rectangle, backColor);                }                DrawBackgroundImage(e.Graphics, Control.BackgroundImage, backColor, Control.BackgroundImageLayout, Control.ClientRectangle, rectangle, autoScrollPosition, Control.RightToLeft);            }            else            {                PaintBackColor(e, rectangle, backColor);            }        }        private static void PaintBackColor(DotNet.Windows.Forms.Internal.PaintEventArgs e, Rectangle rectangle, System.Drawing.Color backColor)        {            System.Drawing.Color nearestColor = backColor;            if (nearestColor.A == 0xff)            {                using (WindowsGraphics graphics = ((e.HDC != IntPtr.Zero) && ((short)Screen.PrimaryScreen.BitsPerPixel > 8)) ? WindowsGraphics.FromHdc(e.HDC) : WindowsGraphics.FromGraphics(e.Graphics))                {                    nearestColor = graphics.GetNearestColor(nearestColor);                    using (WindowsBrush brush = new WindowsSolidBrush(graphics.DeviceContext, nearestColor))                    {                        graphics.FillRectangle(brush, rectangle);                    }                    return;                }            }            if (nearestColor.A > 0)            {                using (Brush brush2 = new SolidBrush(nearestColor))                {                    e.Graphics.FillRectangle(brush2, rectangle);                }            }        }        private void PaintWithErrorHandling(DotNet.Windows.Forms.Internal.PaintEventArgs e, short layer)        {            try            {                this.CacheTextInternal = true;                bool flag = true;                try                {                    switch (layer)                    {                        case 1:                            this.OnPaintBackground(e);                            break;                        case 2:                            this.OnPaint(e);                            break;                    }                    flag = false;                }                finally                {                    if (flag)                    {                        this.SetState(0x400000, true);                        Control.Invalidate();                    }                }            }            finally            {                this.CacheTextInternal = false;            }        }        void IWindowTarget.OnMessage(ref Message m)        {            if (m.Msg == 15)            {                WmPaint(ref m);                return;            }            Target.OnMessage(ref m);        }        #endregion    }}
View Code

 

 

 

http://files.cnblogs.com/dotnet-org-cn/DotNet.Framework.rar

 

最后打个小广告:中国.NET协会(http://www.dotnet.org.cn)
腾讯企鹅群:45132984中国.NET协会
博客园地址:http://http://www.cnblogs.com/dotnet-org-cn
     国内唯一一个以非盈利的.NET协会,致力打造国内具有权威性、价值性的.NET协会。

 

自己画WinForm 皮肤包括默认控件