分享一个很久之前写的一个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); } } }