主要利用CBT钩子,NativeWindow来实现。可实现动态换皮肤插件修改窗体显示外观。
我们先定义一个自定义组件
<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 动态加载皮肤资源
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);
}
}
}
</pre>
新增一个皮肤资源类,主要用于存储皮肤文件中的信息
<pre>
namespace Skin
{
public class SkinResource
{
public Color CaptionColor {get;set;}
public Color CaptionBackgroundColor {get;set;}
}
}
</pre>
新增一个类,主要实现对窗体的消息接管和绘制
<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 构造函数
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>
主要提供了窗体非客户区背景色和标题文字颜色。我们可以做个皮肤编辑工具,将用户选择的颜色按上面的命名空间和类生成dll文件。
下面进行测试:
将皮肤文件项目编译,生成dll文件放在debug目录下面的Skin文件夹下。
在窗体的构造函数中,调用
<pre>
LySkinEngine SkinEngine = new LySkinEngine();
SkinEngine.SetSkin("SkinFile");
</pre>
SetSkin方法的参数是我们皮肤dll文件的名称,我们可以新建多个皮肤文件,在此处动态切换。
运行效果如下
我们修改调用的皮肤名称
<pre>
LySkinEngine SkinEngine = new LySkinEngine();
SkinEngine.SetSkin("SkinFile1");
</pre>
效果如下:
基本效果已实现,还需要继续完善。