分享一个很久之前写的一个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");//生成实例 Skin1Object 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;}#endregionpublic 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

新增一个皮肤资源类,主要用于存储皮肤文件中的信息

namespace Skin
{
public class SkinResource
{
public Color CaptionColor {get;set;}
public Color CaptionBackgroundColor {get;set;}
}
}

新增一个类,主要实现对窗体的消息接管和绘制

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 WPARAMconst 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 构造函数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}
}

View Code

新建一个项目,这个项目是皮肤文件。

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; }}}
}

主要提供了窗体非客户区背景色和标题文字颜色。我们可以做个皮肤编辑工具,将用户选择的颜色按上面的命名空间和类生成dll文件。

下面进行测试:
将皮肤文件项目编译,生成dll文件放在debug目录下面的Skin文件夹下。

image.png

在窗体的构造函数中,调用

LySkinEngine SkinEngine = new LySkinEngine();
SkinEngine.SetSkin("SkinFile");

SetSkin方法的参数是我们皮肤dll文件的名称,我们可以新建多个皮肤文件,在此处动态切换。

运行效果如下

image.png

我们修改调用的皮肤名称

LySkinEngine SkinEngine = new LySkinEngine();
SkinEngine.SetSkin("SkinFile1");

效果如下:

image.png

基本效果已实现,还需要继续完善。

转载于:https://www.cnblogs.com/czly/p/9117143.html

Winform 自定义窗体皮肤组件相关推荐

  1. C# WINFORM 自定义窗体 皮肤[转]

    跟我学做c#皮肤美化(一) --概述与导航 每每看着QQ,360等等那些软件漂亮的外衣时,你是不是总是在想我的软件什么时候才能穿上这么漂亮的外衣呢?不过现在当你看到这篇文章的时候不必再发出这样的疑问了 ...

  2. 解决winform自定义窗体在扩展显示器最大化不能充满屏幕

    参考:(60条消息) winForm在多显示器(主显示器 + 扩展显示器)上显示最大化和还原操作._梦的远方~的博客-CSDN博客 原因: 我开发用笔记本,缩放设置为150%:同时外接一个扩展屏,缩放 ...

  3. winform自定义窗体边框样式模板(支持四周边框拖拽改变窗体大小,支持鼠标拖动头部移动窗体)

    winform自己的边框已经过时,但小伙伴们又觉得自定义太过麻烦.本文将手把手教你自定义winform边框样式,并提供源代码链接(可直接作为模板使用).话不多说,直接上操作步骤. 先上一张完成截图 一 ...

  4. c#winform自定义窗体(含源码)

    第一步:首先引用DLL 再窗体中继承DevComponents.DotNetBar.OfficeForm public partial class MainForm : DevComponents.D ...

  5. WinForm经典窗体皮肤[重绘]

    先上图看看效果: 1.默认经典 2.蓝色炫雅 3.蓝色经典 4.黑色炫雅 5.黑色经典 注:代码是几年前从网上找到的,好像是在CodeProject上,代码整理中,稍候公开源码... 转载于:http ...

  6. C# Winform 窗体美化(十、自定义窗体)

    十.自定义窗体 写在前面 最近在做 winform 应用程序,需要自定义一种窗口的样式,所以就随便搞了一个简单的窗口. 效果图 有两种样式,界面如下: 无标题: 有标题: 关键词 1.黑色描边边框 对 ...

  7. 自定义窗体设计器-控件测试

    自定义窗体设计器-控件测试 基于.net2的自定义窗体设计器控件(类似visual studio的vb,c#设计器,其实就是vs2005的设计器) 控件由四部分组成:工具栏,工具箱,绘图设计区,属性框 ...

  8. 通过用 .NET 生成自定义窗体设计器来定制应用程序

    本文讨论: ? 设计时环境基本原理 ? 窗体设计器体系结构 ? Visual Studio .NET 中窗体设计器的实现 ? 为自己的应用程序编写窗体设计器而需要实现的服务 在很多年中,MFC 一直是 ...

  9. 一个磁性窗体VCL组件的具体实现

    一个磁性窗体VCL组件的具体实现 副标题: 作者:佚名 文章来源:大富翁 点击数:52 更新时间:2005-2-25     文:陈达军 日期:2003-10-29 记得<程序员>杂志中曾 ...

最新文章

  1. Linux容器的发展历史及其未来趋势
  2. 软件战争中的小插曲:比较搜狗拼音和QQ拼音输入法
  3. 摘录cocos2d-x 从环境搭建到win32项目移植android平台
  4. 力的作用与形态的分类
  5. 「JupyterNotebook」Linux下安装Anaconda3以及后续打开jupyter notebook
  6. pyltp在ubuntu20.04下面的安装办法
  7. 调查一下 大家用vs时做网页时,都用的什么标准?
  8. LeetCode 128. 最长连续序列 golang
  9. 一些ASP.NET不能调试问题的解决办法!
  10. [html] 如何让table的边框双线变单线?
  11. 干货|MIT线性代数课程精细笔记6-子空间与零空间
  12. 移动云TeaTalk(长沙站)| 聚焦“云网一体”发展新机遇
  13. android 重新设置lcd分辨率,wm命令使用方法(修改android 分辨率)修改
  14. this.fields.get(c) is undefined
  15. 四、Mysql安装多实例
  16. FFMPEG结构体分析:AVCodecContext
  17. html文件执行php语句
  18. IDEA 常用快捷键 常用插件 1
  19. 系统进程网络流量监控软件
  20. 135、137、138、139和445端口

热门文章

  1. Android Listview 点击item变黄色
  2. 保留IP地址(特殊IP地址)
  3. iPhone4 FaceTime 联通官方教程
  4. Vue—基础概念—组建化
  5. 分布式实时计算—Storm—基础介绍
  6. python 字典添加元素
  7. TCP连接之报文首部
  8. Java基础(39)Arrays.binarySearch方法
  9. 【Luogu】P1896互不侵犯King(状压DP)
  10. 没有学过功夫能否练神功