分享一个很久之前写的一个Winform换肤组件。

主要利用CBT钩子,NativeWindow来实现。可实现动态换皮肤插件修改窗体显示外观。
我们先定义一个自定义组件

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 动态加载皮肤资源
    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);

        //标题背景
        PropertyInfo pi = type.GetProperty("CaptionBackgroundColor");
        tmpResource.CaptionBackgroundColor = (Color)pi.GetValue(obj, null);
        //标题前景色
        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);
    }

}
}
View Code

相关文章: