Winform 自定義窗體皮膚組件

主要利用CBT鉤子肆饶,NativeWindow來實現(xiàn)。可實現(xiàn)動態(tài)換皮膚插件修改窗體顯示外觀候学。
我們先定義一個自定義組件
<pre>
using Skin;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace SkinControl
{
public class LySkinEngine : Component
{
#region 字段
public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);

    private static HookProc _cbtHook;

    private static IntPtr Hook;

    private static string m_SkinName = "";
    #endregion

    #region API
    /// <summary>
    /// SetWindowsHookEx
    /// </summary>
    /// <param name="idHook"></param>
    /// <param name="lpfn"></param>
    /// <param name="hMod"></param>
    /// <param name="dwThreadId"></param>
    /// <returns></returns>
    [DllImport("User32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, int hMod, int dwThreadId);

    /// <summary>
    /// CallNextHookEx
    /// </summary>
    /// <param name="hhk"></param>
    /// <param name="nCode"></param>
    /// <param name="wParam"></param>
    /// <param name="lParam"></param>
    /// <returns></returns>
    [DllImport("User32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

    /// <summary>
    /// UnhookWindowsHookEx
    /// </summary>
    /// <param name="hhk"></param>
    /// <returns></returns>
    [DllImport("User32.dll", CharSet = CharSet.Auto)]
    public static extern bool UnhookWindowsHookEx(IntPtr hhk);
    #endregion

    #region FnHookProc
    /// <summary>
    /// FnHookProc
    /// </summary>
    /// <param name="nCode"></param>
    /// <param name="wParam"></param>
    /// <param name="lParam"></param>
    /// <returns></returns>
    private static IntPtr FnHookProc(int nCode, IntPtr wParam, IntPtr lParam)
    {

        switch (nCode)
        {
            case 5:
                Control control = Control.FromHandle(wParam);

                if (control != null)
                {

                    Skin.SkinResource tmpSkinClass = GetSkin();

                    FormBase frmBase = new FormBase(control as Form, tmpSkinClass);

                }
                break;
            default:
                break;
        }
        return CallNextHookEx(Hook, nCode, wParam, lParam);
    }
    #endregion

    #region 動態(tài)加載皮膚資源
    private static SkinResource GetSkin()
    {
        SkinResource tmpResource = new SkinResource();

        Assembly ass = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory + @"\Skin\" + m_SkinName + @".dll");

        Type type = ass.GetType("SkinFile.Skin");

        //生成實例 Skin1
        Object obj = Activator.CreateInstance(type);

        //標(biāo)題背景
        PropertyInfo pi = type.GetProperty("CaptionBackgroundColor");
        tmpResource.CaptionBackgroundColor = (Color)pi.GetValue(obj, null);
        //標(biāo)題前景色
        PropertyInfo pi1 = type.GetProperty("CaptionColor");
        tmpResource.CaptionColor = (Color)pi1.GetValue(obj, null);


        return tmpResource;
    }
    #endregion

   
    public void SetSkin(string varSkinName)
    {
        m_SkinName = varSkinName;
        if (Hook == IntPtr.Zero)
        {
            _cbtHook = new HookProc(FnHookProc);
            Hook = SetWindowsHookEx(5, _cbtHook, 0, AppDomain.GetCurrentThreadId());
            Application.ApplicationExit += new EventHandler(Application_ApplicationExit);
        }
    }

    /// <summary>
    /// Application_ApplicationExit
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void Application_ApplicationExit(object sender, EventArgs e)
    {
        //Engine.Dispose(false);
        UnhookWindowsHookEx(Hook);
    }

}

}

</pre>

新增一個皮膚資源類,主要用于存儲皮膚文件中的信息
<pre>
namespace Skin
{
public class SkinResource
{
public Color CaptionColor {get;set;}
public Color CaptionBackgroundColor {get;set;}

}

}

</pre>

新增一個類纵散,主要實現(xiàn)對窗體的消息接管和繪制
<pre>

namespace Skin
{
public partial class FormBase : NativeWindow
{
Form m_f = null;

    public FormBase(Form varForm,  Skin.SkinResource varSkin)
    {
        try
        {
            m_f = varForm;
            AssignHandle(m_f.Handle);
            m_f.HandleDestroyed += new EventHandler(this.OnHandleDestroyed);

            CloseButtonImage = Resource1.close_normal;
            CloseButtonHoverImage = Resource1.close_highlight;
            CloseButtonPressDownImage = Resource1.close_press;

            MaximumButtonImage = Resource1.max_normal;
            MaximumButtonHoverImage = Resource1.max_highlight;
            MaximumButtonPressDownImage = Resource1.max_press;

            MaximumNormalButtonImage = Resource1.restore_normal;
            MaximumNormalButtonHoverImage = Resource1.restore_highlight;
            MaximumNormalButtonPressDownImage = Resource1.restore_press;

            MinimumButtonImage = Resource1.min_normal;
            MinimumButtonHoverImage = Resource1.min_highlight;
            MinimumButtonPressDownImage = Resource1.min_press;

            HelpButtonImage = Resource1.skin_normal;
            HelpButtonHoverImage = Resource1.skin_highlight;
            HelpButtonPressDownImage = Resource1.skin_press;

            CaptionColor = varSkin.CaptionColor;
            CaptionBackgroundColor = varSkin.CaptionBackgroundColor;

        }
        catch(Exception ex)
        {
        }
     
    }


    #region 字段

    struct _NonClientSizeInfo
    {
        public Size CaptionButtonSize;
        public Size BorderSize;
        public int CaptionHeight;
        public Rectangle CaptionRect;
        public Rectangle Rect;
        public Rectangle ClientRect;
        public int Width;
        public int Height;
    };

    #region 常量

    const int WM_NCACTIVATE = 0x86;
    const int WM_NCPAINT = 0x85;
    const int WM_NCLBUTTONDOWN = 0xA1;
    const int WM_NCRBUTTONDOWN = 0x00A4;
    const int WM_NCRBUTTONUP = 0x00A5;
    const int WM_NCMOUSEMOVE = 0x00A0;
    const int WM_NCLBUTTONUP = 0x00A2;
    const int WM_NCCALCSIZE = 0x0083;
    const int WM_NCMOUSEHOVER = 0x02A0;
    const int WM_NCMOUSELEAVE = 0x02A2;
    const int WM_NCHITTEST = 0x0084;
    const int WM_NCCREATE = 0x0081;
    //const int WM_RBUTTONUP = 0x0205;

    const int WM_LBUTTONDOWN = 0x0201;
    const int WM_CAPTURECHANGED = 0x0215;
    const int WM_LBUTTONUP = 0x0202;
    const int WM_SETCURSOR = 0x0020;
    const int WM_CLOSE = 0x0010;
    const int WM_SYSCOMMAND = 0x0112;
    const int WM_MOUSEMOVE = 0x0200;
    const int WM_SIZE = 0x0005;
    const int WM_SIZING = 0x0214;
    const int WM_GETMINMAXINFO = 0x0024;
    const int WM_ENTERSIZEMOVE = 0x0231;
    const int WM_WINDOWPOSCHANGING = 0x0046;


    // FOR WM_SIZING MSG WPARAM
    const int WMSZ_BOTTOM = 6;
    const int WMSZ_BOTTOMLEFT = 7;
    const int WMSZ_BOTTOMRIGHT = 8;
    const int WMSZ_LEFT = 1;
    const int WMSZ_RIGHT = 2;
    const int WMSZ_TOP = 3;
    const int WMSZ_TOPLEFT = 4;
    const int WMSZ_TOPRIGHT = 5;

    // left mouse button is down.
    const int MK_LBUTTON = 0x0001;

    const int SC_CLOSE = 0xF060;
    const int SC_MAXIMIZE = 0xF030;
    const int SC_MINIMIZE = 0xF020;
    const int SC_RESTORE = 0xF120;
    const int SC_CONTEXTHELP = 0xF180;

    const int HTCAPTION = 2;
    const int HTCLOSE = 20;
    const int HTHELP = 21;
    const int HTMAXBUTTON = 9;
    const int HTMINBUTTON = 8;
    const int HTTOP = 12;

    const int SM_CYBORDER = 6;
    const int SM_CXBORDER = 5;
    const int SM_CYCAPTION = 4;

    const int CS_DropSHADOW = 0x20000;
    const int GCL_STYLE = (-26);

    #endregion
    #endregion

    #region windows api

    [DllImport("User32.dll")]
    private static extern IntPtr GetWindowDC(IntPtr hwnd);
    [DllImport("User32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool GetWindowRect(IntPtr hwnd, ref Rectangle rect);
    [DllImport("User32.dll")]
    private static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern int SetClassLong(IntPtr hwnd, int nIndex, int dwNewLong);
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern int GetClassLong(IntPtr hwnd, int nIndex);

    #endregion

    #region 構(gòu)造函數(shù)
    internal void OnHandleCreated(object sender, EventArgs e)
    {
        AssignHandle(((Form)sender).Handle);
    }

    internal void OnHandleDestroyed(object sender, EventArgs e)
    {
        ReleaseHandle();
    }
    #endregion

    #region 屬性

    [Category("ControlBox")]
    [Description("Close button image in control box.")]
    [DisplayName("CloseButtonImage")]
    [DesignOnly(true)]
    public Image CloseButtonImage { get; set; }

    [Category("ControlBox")]
    [Description("Close button image pressed down in control box.")]
    [DisplayName("CloseButtonPressDownImage")]
    [DesignOnly(true)]
    public Image CloseButtonPressDownImage { get; set; }

    [Category("ControlBox")]
    [Description("Close button image hover in control box.")]
    [DisplayName("CloseButtonHoverImage")]
    [DesignOnly(true)]
    public Image CloseButtonHoverImage { get; set; }

    [Category("ControlBox")]
    [Description("Maximum button image in control box.")]
    [DisplayName("MaximumButtonImage")]
    [DesignOnly(true)]
    public Image MaximumButtonImage { get; set; }

    [Category("ControlBox")]
    [Description("Maximum button hover image in control box.")]
    [DisplayName("MaximumButtonHoverImage")]
    [DesignOnly(true)]
    public Image MaximumButtonHoverImage { get; set; }

    [Category("ControlBox")]
    [Description("Maximum button pressed down image in control box.")]
    [DisplayName("MaximumButtonPressDownImage")]
    [DesignOnly(true)]
    public Image MaximumButtonPressDownImage { get; set; }

    [Category("ControlBox")]
    [Description("Maximum Normal button image in control box.")]
    [DisplayName("MaximumNormalButtonImage")]
    [DesignOnly(true)]
    public Image MaximumNormalButtonImage { get; set; }

    [Category("ControlBox")]
    [Description("Maximum Normal button hover image in control box.")]
    [DisplayName("MaximumNormalButtonHoverImage")]
    [DesignOnly(true)]
    public Image MaximumNormalButtonHoverImage { get; set; }

    [Category("ControlBox")]
    [Description("Maximum Normal button pressed down image in control box.")]
    [DisplayName("MaximumNormalButtonPressDownImage")]
    [DesignOnly(true)]
    public Image MaximumNormalButtonPressDownImage { get; set; }

    [Category("ControlBox")]
    [Description("Minimum button image in control box.")]
    [DisplayName("MinimumButtonImage")]
    [DesignOnly(true)]
    public Image MinimumButtonImage { get; set; }

    [Category("ControlBox")]
    [Description("Minimum button hover image in control box.")]
    [DisplayName("MinimumButtonHoverImage")]
    [DesignOnly(true)]
    public Image MinimumButtonHoverImage { get; set; }

    [Category("ControlBox")]
    [Description("Minimum button pressed down image in control box.")]
    [DisplayName("MinimumButtonPressDownImage")]
    [DesignOnly(true)]
    public Image MinimumButtonPressDownImage { get; set; }

    [Category("ControlBox")]
    [Description("Help button image in control box.")]
    [DisplayName("HelpButtonImage")]
    [DesignOnly(true)]
    public Image HelpButtonImage { get; set; }

    [Category("ControlBox")]
    [Description("Help button hover image in control box.")]
    [DisplayName("HelpButtonHoverImage")]
    [DesignOnly(true)]
    public Image HelpButtonHoverImage { get; set; }

    [Category("ControlBox")]
    [Description("Help button pressed down image in control box.")]
    [DisplayName("HelpButtonPressDownImage")]
    [DesignOnly(true)]
    public Image HelpButtonPressDownImage { get; set; }

    [Category("CaptionColor")]
    [Description("The color of caption.")]
    [DisplayName("CaptionColor")]
    [DefaultValue(typeof(Color), "Black")]
    [Browsable(true)]
    public Color CaptionColor { get; set; }

    [Category("CaptionColor")]
    [Description("The color of caption.")]
    [DisplayName("CaptionBackgroundColor")]
    [DefaultValue(typeof(Color), "Black")]
    [Browsable(true)]
    public Color CaptionBackgroundColor { get; set; }

    [DefaultValue("")]
    [Browsable(true)]
    [Category("ControlBox")]
    public virtual ContextMenuStrip CaptionContextMenu { get; set; }
    #endregion

    #region 方法

    private _NonClientSizeInfo GetNonClientInfo(IntPtr hwnd)
    {
        _NonClientSizeInfo info = new _NonClientSizeInfo();
        info.CaptionButtonSize = SystemInformation.CaptionButtonSize;
        info.CaptionHeight = SystemInformation.CaptionHeight;

        switch (m_f.FormBorderStyle)
        {
            case System.Windows.Forms.FormBorderStyle.Fixed3D:
                info.BorderSize = SystemInformation.FixedFrameBorderSize;
                break;
            case System.Windows.Forms.FormBorderStyle.FixedDialog:
                info.BorderSize = SystemInformation.FixedFrameBorderSize;
                break;
            case System.Windows.Forms.FormBorderStyle.FixedSingle:
                info.BorderSize = SystemInformation.FixedFrameBorderSize;
                break;
            case System.Windows.Forms.FormBorderStyle.FixedToolWindow:
                info.BorderSize = SystemInformation.FixedFrameBorderSize;
                info.CaptionButtonSize = SystemInformation.ToolWindowCaptionButtonSize;
                info.CaptionHeight = SystemInformation.ToolWindowCaptionHeight;
                break;
            case System.Windows.Forms.FormBorderStyle.Sizable:
                info.BorderSize = SystemInformation.FrameBorderSize;
                break;
            case System.Windows.Forms.FormBorderStyle.SizableToolWindow:
                info.CaptionButtonSize = SystemInformation.ToolWindowCaptionButtonSize;
                info.BorderSize = SystemInformation.FrameBorderSize;
                info.CaptionHeight = SystemInformation.ToolWindowCaptionHeight;
                break;
            default:
                info.BorderSize = SystemInformation.BorderSize;
                break;
        }

        Rectangle areatRect = new Rectangle();
        GetWindowRect(hwnd, ref areatRect);

        int width = areatRect.Right - areatRect.Left;
        int height = areatRect.Bottom - areatRect.Top;

        info.Width = width;
        info.Height = height;

        Point xy = new Point(areatRect.Left, areatRect.Top);
        xy.Offset(-areatRect.Left, -areatRect.Top);

        info.CaptionRect = new Rectangle(xy.X, xy.Y + info.BorderSize.Height, width, info.CaptionHeight);
        info.Rect = new Rectangle(xy.X, xy.Y, width, height);
        info.ClientRect = new Rectangle(xy.X + info.BorderSize.Width,
            xy.Y + info.CaptionHeight + info.BorderSize.Height,
            width - info.BorderSize.Width * 2,
            height - info.CaptionHeight - info.BorderSize.Height * 2);
        
        return info;
    }

    private void DrawTitle(Graphics g, _NonClientSizeInfo ncInfo, bool active)
    {
        try
        {
        
        int titleX;

        if (m_f.ShowIcon &&
             m_f.FormBorderStyle != System.Windows.Forms.FormBorderStyle.FixedToolWindow &&
             m_f.FormBorderStyle != System.Windows.Forms.FormBorderStyle.SizableToolWindow)
        {
            Size iconSize = SystemInformation.SmallIconSize;
            g.DrawIcon(m_f.Icon, new Rectangle(new Point(ncInfo.BorderSize.Width+5, ncInfo.BorderSize.Height + (ncInfo.CaptionHeight - iconSize.Height) / 2+5), iconSize));
            titleX = ncInfo.BorderSize.Width + iconSize.Width + ncInfo.BorderSize.Width+5;
        }
        else
        {
            titleX = ncInfo.BorderSize.Width;
        }

        SizeF captionTitleSize = g.MeasureString(m_f.Text, SystemFonts.CaptionFont);
        g.DrawString(m_f.Text, SystemFonts.CaptionFont, new SolidBrush(CaptionColor),
                new RectangleF(titleX,
                    (ncInfo.BorderSize.Height + ncInfo.CaptionHeight - captionTitleSize.Height) / 2+5,
                    ncInfo.CaptionRect.Width - ncInfo.BorderSize.Width * 2 - SystemInformation.MinimumWindowSize.Width,
                    ncInfo.CaptionRect.Height), StringFormat.GenericTypographic);
            }
        catch(Exception ex)
        {

        }
    }

    private void DrawBorder(Graphics g, _NonClientSizeInfo ncInfo, Brush background, bool active,ref List<Rectangle> varBorders)
    {
        
        int tmpHeight = m_f.Height;
        int tmpWidth = m_f.Width;
        if (ncInfo.Rect.Height != tmpHeight)
        {
            ncInfo.Rect.Height = tmpHeight + ncInfo.BorderSize.Height;
        }
        if (ncInfo.Rect.Width != tmpWidth)
        {
            ncInfo.Rect.Width = tmpWidth + ncInfo.BorderSize.Width;
        }
        

        Rectangle borderTop = new Rectangle(ncInfo.Rect.Left,
                ncInfo.Rect.Top,
                ncInfo.Rect.Left + ncInfo.Rect.Width,
                ncInfo.Rect.Top + ncInfo.BorderSize.Height);
        Rectangle borderLeft = new Rectangle(
                new Point(ncInfo.Rect.Location.X, ncInfo.Rect.Location.Y + ncInfo.BorderSize.Height),
                new Size((int)(ncInfo.BorderSize.Width*2), ncInfo.ClientRect.Height + ncInfo.CaptionHeight + ncInfo.BorderSize.Height));
        Rectangle borderRight = new Rectangle(ncInfo.Rect.Width- 3*ncInfo.BorderSize.Width,
                ncInfo.Rect.Top + ncInfo.BorderSize.Height,
                (int)(ncInfo.BorderSize.Width * 2),
                ncInfo.ClientRect.Height + ncInfo.CaptionHeight + ncInfo.BorderSize.Height);
        Rectangle borderBottom = new Rectangle(ncInfo.Rect.Left + ncInfo.BorderSize.Width,
                ncInfo.Rect.Height - 3*ncInfo.BorderSize.Height,
                ncInfo.Rect.Width - ncInfo.BorderSize.Width ,
                (int)(ncInfo.BorderSize.Height * 2));
        varBorders.Add(borderTop);
        varBorders.Add(borderLeft);
        varBorders.Add(borderRight);
        varBorders.Add(borderBottom);
       
        g.FillRectangle(background, borderTop);
        // left border
        g.FillRectangle(background, borderLeft);
        // right border
        g.FillRectangle(background, borderRight);
        // bottom border
        g.FillRectangle(background, borderBottom);
    }
    private List<Rectangle> m_Borders = null;
    private void DrawCaption(IntPtr hwnd, bool active)
    {
        m_Borders = new List<Rectangle>();
        IntPtr dc;
        Graphics g;
        Size iconSize;
        _NonClientSizeInfo ncInfo;
        Brush backgroundColor = new SolidBrush(CaptionBackgroundColor);
        Brush foregroundColor = new SolidBrush(CaptionColor);

        iconSize = SystemInformation.SmallIconSize;

        dc = GetWindowDC(hwnd);
        ncInfo = GetNonClientInfo(hwnd);
        g = Graphics.FromHdc(dc);

        Rectangle rc = ncInfo.CaptionRect;
        rc.Height = (int)(rc.Height + ncInfo.BorderSize.Height);
        g.FillRectangle(backgroundColor, rc);

        DrawBorder(g, ncInfo, backgroundColor, active, ref m_Borders);
        DrawTitle(g, ncInfo, active);
        DrawControlBox(g, ncInfo, backgroundColor, m_f.ControlBox, m_f.MaximizeBox, m_f.MinimizeBox, m_f.HelpButton);
        g.Dispose();
        ReleaseDC(hwnd, dc);
    }

    private void DrawControlBox(Graphics g, _NonClientSizeInfo info, Brush background, bool closeBtn, bool maxBtn, bool minBtn, bool helpBtn)
    {
        
        int tmpHeight = m_f.Height;
        int tmpWidth = m_f.Width;
        if (info.CaptionRect.Height > tmpHeight)
        {
            info.CaptionRect.Height = tmpHeight;
        }
        if (info.CaptionRect.Width > tmpWidth)
        {
            info.CaptionRect.Width = tmpWidth;
        }
        info.CaptionRect.Height = info.CaptionRect.Height * 2;
     
        
        if (m_f.ControlBox)
        {
            int closeBtnPosX =  info.CaptionRect.Width - info.BorderSize.Width - info.CaptionButtonSize.Width;
            int maxBtnPosX = closeBtnPosX - info.CaptionButtonSize.Width;
            int minBtnPosX = maxBtnPosX - info.CaptionButtonSize.Width;
            int btnPosY = info.BorderSize.Height + (info.CaptionHeight - info.CaptionButtonSize.Height) / 2;

            Rectangle btnRect = new Rectangle(new Point(closeBtnPosX, btnPosY), info.CaptionButtonSize);
            Rectangle maxRect = new Rectangle(new Point(maxBtnPosX, btnPosY), info.CaptionButtonSize);
            Rectangle minRect = new Rectangle(new Point(minBtnPosX, btnPosY), info.CaptionButtonSize);

            Brush backgroundColor = new SolidBrush(CaptionBackgroundColor);

            g.FillRectangle(backgroundColor, btnRect);
            g.FillRectangle(backgroundColor, maxRect);
            g.FillRectangle(backgroundColor, minRect);

            g.DrawImage(CloseButtonImage, btnRect);

            if (m_f.MaximizeBox || m_f.MinimizeBox)
            {
                if (m_f.FormBorderStyle != System.Windows.Forms.FormBorderStyle.FixedToolWindow &&
                    m_f.FormBorderStyle != System.Windows.Forms.FormBorderStyle.SizableToolWindow)
                {
                    if (m_f.WindowState == FormWindowState.Maximized)
                    {
                        g.DrawImage(MaximumNormalButtonImage, maxRect);
                    }
                    else
                    {
                        g.DrawImage(MaximumButtonImage, maxRect);
                    }
                    g.DrawImage(MinimumButtonImage, minRect);
                }
            }
            else if (m_f.HelpButton)
            {
                if (m_f.FormBorderStyle != System.Windows.Forms.FormBorderStyle.FixedToolWindow &&
                    m_f.FormBorderStyle != System.Windows.Forms.FormBorderStyle.SizableToolWindow)
                {
                    g.DrawImage(HelpButtonImage, maxRect);
                }
            }
        }

    }

    protected virtual void OnCaptionContextMenu(int x, int y)
    {
        if (this.CaptionContextMenu != null)
            this.CaptionContextMenu.Show(x, y);
    }

    #endregion

    #region 消息
    private int m_IsDrawButton = 0;
    private int LOBYTE(long p) { return (int)(p & 0x0000FFFF); }
    private int HIBYTE(long p) { return (int)(p >> 16); }

    [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
    protected override void WndProc(ref Message m)
    {
        try
        {
            if (m == null) 
            {
                return;
            }

            if (m_f.FormBorderStyle != System.Windows.Forms.FormBorderStyle.None)
            {
                switch (m.Msg)
                {
                    case WM_NCPAINT:

                        DrawCaption(m.HWnd, Form.ActiveForm == m_f);
                        Console.WriteLine(1);
                        if (m_Borders != null && m_Borders.Count > 0)
                        {
                            for (int i = 0; i < m_Borders.Count; i++)
                            {
                                Console.WriteLine(m_Borders[i].Left + "--" + m_Borders[i].Right + "--" + m_Borders[i].Top + "--" + m_Borders[i].Bottom);
                            }
                        }
                        Console.WriteLine("WM_NCPAINT");
                        return;
                    case WM_NCACTIVATE:
                        Console.WriteLine("WM_NCACTIVATE");
                        if (m.WParam.ToInt32() > 0)
                        {
                            DrawCaption(m.HWnd, m.WParam.ToInt32() > 0);
                            Console.WriteLine(2);
                            return;
                        }
                        else
                        {

                            break;
                        }
                    case WM_NCRBUTTONDOWN:
                        {
                            int posX, posY;
                            int wp = m.WParam.ToInt32();
                            long lp = m.LParam.ToInt64();
                            posX = LOBYTE(lp);
                            posY = HIBYTE(lp);

                            if (wp == HTCAPTION)
                            {
                                Point pt = m_f.PointToClient(new Point(posX, posY));
                                if (this.CaptionContextMenu != null)
                                {
                                    this.CaptionContextMenu.Show(posX, posY);
                                    return;
                                }
                            }
                            break;
                        }
                    case WM_SETCURSOR:

                        if (m_f.ControlBox)
                        {

                            int posX, posY;
                            int wp = m.WParam.ToInt32();
                            long lp = m.LParam.ToInt64();
                            posX = LOBYTE(lp);
                            posY = HIBYTE(lp);

                            Brush backgroundColor = new SolidBrush(CaptionBackgroundColor);
                            _NonClientSizeInfo ncInfo = GetNonClientInfo(m.HWnd);

                            int tmpHeight = m_f.Height;
                            int tmpWidth = m_f.Width;
                            if (ncInfo.CaptionRect.Height > tmpHeight)
                            {
                                ncInfo.CaptionRect.Height = tmpHeight;
                            }
                            if (ncInfo.CaptionRect.Width > tmpWidth)
                            {
                                ncInfo.CaptionRect.Width = tmpWidth;
                            }

                            IntPtr dc = GetWindowDC(m.HWnd);

                            Graphics g = Graphics.FromHdc(dc);
                            int closeBtnPosX = ncInfo.CaptionRect.Left + ncInfo.CaptionRect.Width - ncInfo.BorderSize.Width - ncInfo.CaptionButtonSize.Width;
                            int maxBtnPosX, minBtnPosX;
                            maxBtnPosX = closeBtnPosX - ncInfo.CaptionButtonSize.Width;
                            minBtnPosX = maxBtnPosX - ncInfo.CaptionButtonSize.Width;

                            int btnPosY = ncInfo.BorderSize.Height + (ncInfo.CaptionHeight - ncInfo.CaptionButtonSize.Height) / 2;

                            Rectangle btnRect = new Rectangle(new Point(closeBtnPosX, btnPosY), ncInfo.CaptionButtonSize);
                            Rectangle maxRect = new Rectangle(new Point(maxBtnPosX, btnPosY), ncInfo.CaptionButtonSize);
                            Rectangle minRect = new Rectangle(new Point(minBtnPosX, btnPosY), ncInfo.CaptionButtonSize);
                            if (posX != HTMAXBUTTON && posX != HTMINBUTTON && posX != HTCLOSE)
                            {
                                Console.WriteLine("不在");
                                if (m_IsDrawButton <= 3)
                                {
                                    m_IsDrawButton++;
                                    Console.WriteLine("啊啊");
                                    goto aa;
                                }
                                break;
                            }

                            m_IsDrawButton = 0;
                            Console.WriteLine("在");
                        aa:
                            g.FillRectangle(backgroundColor, btnRect);
                            g.FillRectangle(backgroundColor, maxRect);
                            g.FillRectangle(backgroundColor, minRect);


                            if (posX != HTCLOSE)
                            {
                                g.DrawImage(CloseButtonImage, btnRect);
                            }
                            else if (System.Windows.Forms.Control.MouseButtons != System.Windows.Forms.MouseButtons.Left)
                            {
                                g.DrawImage(CloseButtonHoverImage, btnRect);
                            }
                            else
                            {
                                g.DrawImage(CloseButtonPressDownImage, btnRect);
                            }

                            if (m_f.MaximizeBox || m_f.MinimizeBox)
                            {
                                if (m_f.FormBorderStyle != System.Windows.Forms.FormBorderStyle.FixedToolWindow &&
                                    m_f.FormBorderStyle != System.Windows.Forms.FormBorderStyle.SizableToolWindow)
                                {
                                    if (m_f.WindowState == FormWindowState.Maximized)
                                    {
                                        if (m_f.MaximizeBox)
                                        {
                                            if (posX != HTMAXBUTTON)
                                            {
                                                g.DrawImage(MaximumNormalButtonImage, maxRect);
                                            }
                                            else if (System.Windows.Forms.Control.MouseButtons != System.Windows.Forms.MouseButtons.Left)
                                            {
                                                g.DrawImage(MaximumNormalButtonHoverImage, maxRect);
                                            }
                                            else
                                            {
                                                g.DrawImage(MaximumNormalButtonPressDownImage, maxRect);
                                            }
                                        }
                                        else
                                        {
                                            g.DrawImage(MaximumNormalButtonImage, maxRect);
                                        }
                                    }
                                    else
                                    {
                                        if (m_f.MaximizeBox)
                                        {
                                            if (posX != HTMAXBUTTON)
                                            {
                                                g.DrawImage(MaximumButtonImage, maxRect);
                                            }
                                            else if (System.Windows.Forms.Control.MouseButtons != System.Windows.Forms.MouseButtons.Left)
                                            {
                                                g.DrawImage(MaximumButtonHoverImage, maxRect);
                                            }
                                            else
                                            {
                                                g.DrawImage(MaximumButtonPressDownImage, maxRect);
                                            }
                                        }
                                        else
                                        {
                                            g.DrawImage(MaximumButtonImage, maxRect);
                                        }
                                    }

                                    if (m_f.MinimizeBox)
                                    {
                                        if (posX != HTMINBUTTON)
                                        {
                                            g.DrawImage(MinimumButtonImage, minRect);
                                        }
                                        else if (System.Windows.Forms.Control.MouseButtons != System.Windows.Forms.MouseButtons.Left)
                                        {
                                            g.DrawImage(MinimumButtonHoverImage, minRect);
                                        }
                                        else
                                        {
                                            g.DrawImage(MinimumButtonPressDownImage, minRect);
                                        }
                                    }
                                    else
                                    {
                                        g.DrawImage(MinimumButtonImage, minRect);
                                    }
                                }
                            }
                            else if (m_f.HelpButton)
                            {
                                if (m_f.FormBorderStyle != System.Windows.Forms.FormBorderStyle.FixedToolWindow &&
                                    m_f.FormBorderStyle != System.Windows.Forms.FormBorderStyle.SizableToolWindow)
                                {
                                    if (posX != HTHELP)
                                    {
                                        g.DrawImage(HelpButtonImage, maxRect);
                                    }
                                    else if (System.Windows.Forms.Control.MouseButtons != System.Windows.Forms.MouseButtons.Left)
                                    {
                                        g.DrawImage(HelpButtonHoverImage, maxRect);
                                    }
                                    else
                                    {
                                        g.DrawImage(HelpButtonPressDownImage, maxRect);
                                    }
                                }
                            }
                            // Application.DoEvents();
                            g.Dispose();
                            ReleaseDC(m.HWnd, dc);
                        }
                        break;
                    case WM_NCLBUTTONUP:
                        {
                            int wp = m.WParam.ToInt32();
                            switch (wp)
                            {
                                case HTCLOSE:
                                    m.Msg = WM_SYSCOMMAND;
                                    m.WParam = new IntPtr(SC_CLOSE);
                                    break;
                                case HTMAXBUTTON:
                                    if (m_f.MaximizeBox)
                                    {
                                        m.Msg = WM_SYSCOMMAND;
                                        if (m_f.WindowState == FormWindowState.Maximized)
                                        {
                                            m.WParam = new IntPtr(SC_RESTORE);
                                        }
                                        else
                                        {
                                            m.WParam = new IntPtr(SC_MAXIMIZE);
                                        }
                                    }
                                    break;
                                case HTMINBUTTON:
                                    if (m_f.MinimizeBox)
                                    {
                                        m.Msg = WM_SYSCOMMAND;
                                        m.WParam = new IntPtr(SC_MINIMIZE);
                                    }
                                    break;
                                case HTHELP:
                                    m.Msg = WM_SYSCOMMAND;
                                    m.WParam = new IntPtr(SC_CONTEXTHELP);
                                    break;
                                default:
                                    break;
                            }

                            break;
                        }

                    case WM_NCLBUTTONDOWN:
                        if (m_f.ControlBox)
                        {
                            bool ret = false;
                            int posX, posY;
                            int wp = m.WParam.ToInt32();
                            long lp = m.LParam.ToInt64();
                            posX = LOBYTE(lp);
                            posY = HIBYTE(lp);

                            _NonClientSizeInfo ncInfo = GetNonClientInfo(m.HWnd);
                            IntPtr dc = GetWindowDC(m.HWnd);
                            Brush backgroundColor = new SolidBrush(CaptionBackgroundColor);

                            Graphics g = Graphics.FromHdc(dc);
                            int closeBtnPosX = ncInfo.CaptionRect.Left + ncInfo.CaptionRect.Width - ncInfo.BorderSize.Width - ncInfo.CaptionButtonSize.Width;
                            int maxBtnPosX, minBtnPosX;
                            int btnPosY = ncInfo.BorderSize.Height + (ncInfo.CaptionHeight - ncInfo.CaptionButtonSize.Height) / 2;
                            maxBtnPosX = closeBtnPosX - ncInfo.CaptionButtonSize.Width;
                            minBtnPosX = maxBtnPosX - ncInfo.CaptionButtonSize.Width;

                            Rectangle btnRect = new Rectangle(new Point(closeBtnPosX, btnPosY), ncInfo.CaptionButtonSize);
                            Rectangle maxRect = new Rectangle(new Point(maxBtnPosX, btnPosY), ncInfo.CaptionButtonSize);
                            Rectangle minRect = new Rectangle(new Point(minBtnPosX, btnPosY), ncInfo.CaptionButtonSize);

                            if (wp != HTMAXBUTTON && wp != HTMINBUTTON && wp != HTCLOSE)
                            {
                                break;
                            }

                            g.FillRectangle(backgroundColor, btnRect);
                            g.FillRectangle(backgroundColor, maxRect);
                            g.FillRectangle(backgroundColor, minRect);

                            if (wp == HTCLOSE)
                            {
                                g.DrawImage(CloseButtonPressDownImage, btnRect);
                                ret = true;
                            }
                            else
                            {
                                g.DrawImage(CloseButtonImage, btnRect);
                            }

                            if (m_f.MaximizeBox || m_f.MinimizeBox)
                            {
                                if (m_f.FormBorderStyle != System.Windows.Forms.FormBorderStyle.SizableToolWindow &&
                                    m_f.FormBorderStyle != System.Windows.Forms.FormBorderStyle.FixedToolWindow)
                                {
                                    if (m_f.WindowState == FormWindowState.Maximized)
                                    {
                                        if (wp == HTMAXBUTTON && m_f.MaximizeBox)
                                        {
                                            minBtnPosX = maxBtnPosX - ncInfo.CaptionButtonSize.Width;
                                            g.DrawImage(MaximumNormalButtonPressDownImage, maxRect);
                                            ret = true;
                                        }
                                        else
                                        {
                                            g.DrawImage(MaximumNormalButtonImage, maxRect);
                                        }
                                    }
                                    else
                                    {
                                        if (wp == HTMAXBUTTON && m_f.MaximizeBox)
                                        {
                                            minBtnPosX = maxBtnPosX - ncInfo.CaptionButtonSize.Width;
                                            g.DrawImage(MaximumButtonPressDownImage, maxRect);
                                            ret = true;
                                        }
                                        else
                                        {
                                            g.DrawImage(MaximumButtonImage, maxRect);
                                        }
                                    }
                                    if (wp == HTMINBUTTON && m_f.MinimizeBox)
                                    {
                                        g.DrawImage(MinimumButtonPressDownImage, minRect);
                                        ret = true;
                                    }
                                    else
                                    {
                                        g.DrawImage(MinimumButtonImage, minRect);
                                    }
                                }
                            }
                            else if (m_f.HelpButton)
                            {
                                if (m_f.FormBorderStyle != System.Windows.Forms.FormBorderStyle.FixedToolWindow &&
                                    m_f.FormBorderStyle != System.Windows.Forms.FormBorderStyle.SizableToolWindow)
                                {
                                    if (wp == HTHELP)
                                    {
                                        g.DrawImage(HelpButtonPressDownImage, maxRect);
                                        ret = true;
                                    }
                                    else
                                    {
                                        g.DrawImage(HelpButtonImage, maxRect);
                                    }
                                }
                            }

                            g.Dispose();
                            ReleaseDC(m.HWnd, dc);

                            if (ret)
                                return;
                        }
                        break;
                }
            }
            try
            {
                base.WndProc(ref m);
            }
            catch (Exception ex)
            { }

            if (m.Msg == WM_NCACTIVATE && m_f.FormBorderStyle != FormBorderStyle.None)
            {
                if (m.WParam.ToInt32() <= 0)
                {
                    DrawCaption(m.HWnd, m.WParam.ToInt32() > 0);
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    #endregion


}

}

</pre>

新建一個項目梳码,這個項目是皮膚文件。
<pre>

namespace SkinFile
{
public class Skin
{
private Color _CaptionColor=Color.Blue;

    public Color CaptionColor
    {
        get { return _CaptionColor; }
        set { _CaptionColor = value; }
    }

    private Color _CaptionBackgroundColor=Color.Green;

    public Color CaptionBackgroundColor
    {
        get { return _CaptionBackgroundColor; }
        set { _CaptionBackgroundColor = value; }
    }


}

}
</pre>
主要提供了窗體非客戶區(qū)背景色和標(biāo)題文字顏色伍掀。我們可以做個皮膚編輯工具掰茶,將用戶選擇的顏色按上面的命名空間和類生成dll文件。

下面進行測試:
將皮膚文件項目編譯蜜笤,生成dll文件放在debug目錄下面的Skin文件夾下濒蒋。


image.png

在窗體的構(gòu)造函數(shù)中,調(diào)用
<pre>
LySkinEngine SkinEngine = new LySkinEngine();
SkinEngine.SetSkin("SkinFile");
</pre>
SetSkin方法的參數(shù)是我們皮膚dll文件的名稱把兔,我們可以新建多個皮膚文件沪伙,在此處動態(tài)切換瓮顽。

運行效果如下


image.png

我們修改調(diào)用的皮膚名稱
<pre>
LySkinEngine SkinEngine = new LySkinEngine();
SkinEngine.SetSkin("SkinFile1");
</pre>
效果如下:


image.png

基本效果已實現(xiàn),還需要繼續(xù)完善焰坪。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末趣倾,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子某饰,更是在濱河造成了極大的恐慌儒恋,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件黔漂,死亡現(xiàn)場離奇詭異诫尽,居然都是意外死亡,警方通過查閱死者的電腦和手機炬守,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門牧嫉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人减途,你說我怎么就攤上這事酣藻。” “怎么了鳍置?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵辽剧,是天一觀的道長。 經(jīng)常有香客問我税产,道長怕轿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任辟拷,我火速辦了婚禮撞羽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘衫冻。我一直安慰自己诀紊,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布隅俘。 她就那樣靜靜地躺著渡紫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪考赛。 梳的紋絲不亂的頭發(fā)上惕澎,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機與錄音颜骤,去河邊找鬼唧喉。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的八孝。 我是一名探鬼主播董朝,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼干跛!你這毒婦竟也來了子姜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤楼入,失蹤者是張志新(化名)和其女友劉穎哥捕,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嘉熊,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡遥赚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了阐肤。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凫佛。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖孕惜,靈堂內(nèi)的尸體忽然破棺而出愧薛,到底是詐尸還是另有隱情,我是刑警寧澤衫画,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布厚满,位于F島的核電站,受9級特大地震影響碧磅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜遵馆,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一鲸郊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧货邓,春花似錦秆撮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至戈二,卻和暖如春舒裤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背觉吭。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工腾供, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓伴鳖,卻偏偏與公主長得像节值,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子榜聂,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 一搞疗、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡單分配策略的問題地址空間不隔離內(nèi)存使用效率低程序運行的地址不確定 關(guān)于...
    SeanCST閱讀 7,806評論 0 27
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,074評論 25 707
  • 1、窗體 1须肆、常用屬性 (1)Name屬性:用來獲取或設(shè)置窗體的名稱拆宛,在應(yīng)用程序中可通過Name屬性來引用窗體。 ...
    Moment__格調(diào)閱讀 4,547評論 0 11
  • 不知道冬天是什么顏色 只是別把難得的溫暖埋沒 趕在天亮之前看看風(fēng)景 于是你就成了那天上的星星 我們一直蕩漾在城市的...
    愚木的簡書閱讀 81評論 0 0
  • 常見的為正方體擁有顏色不同的六個面薪铜! 手指的每次觸動蛤肌,旋轉(zhuǎn)都會改變之前的結(jié)構(gòu),碰撞出無數(shù)的組合瘤礁。任何一小塊遇見另一...
    穗苗閱讀 187評論 0 1