摘要

windows桌面应用程序都有标准的标题栏和边框,大部分程序也默认使用这些样式,一些对视觉效果要求较高的程序,如QQ, MSN,迅雷等聊天工具的样式则与传统的windows程序大不相同,其中迅雷还将他们的BOLT界面引擎开放,使得大家也可以创建类似迅雷一样的界面。那么这些软件的界面是怎样实现的呢,使用C#是否也可以实现类似界面?

重绘方式

常见的自定义标题栏和边框的方式有两种,一种是隐藏标题栏和边框(称为非客户区),然后在客户区(可以放置控件的空间)使用一些常用的控件和图片来表示边框,这种方式较简单而麻烦,但如标题栏的拖动,边框的拖拽来改变窗体大小等效果,则有需要重新实现,另外有些客户区的鼠标事件,控件布局等也需要注意调整;另一种则是大部分软件实现方式,也较难一些;它利用windows的消息机制,截获windows消息,从而改变消息的行为。即windows的一些消息,会引起窗体绘制或重绘标题栏和边框的行为,因此只要结果这部分消息,然后开发人员自己处理绘制过程,并忽略默认行为,从而达到自定义的目的。

C#绘制接口

windows消息对于C#开发新手来说较生疏,原因是.net已经将windows消息机制进行了封装,使得我们很难发现windows消息的踪迹,其实它是以另一个身份存在着--事件。如控件的OnClick,Mouse等事件,都是对windows消息的封装,这样的目的更容易理解,和运用。.net提供了处理消息的接口,常用的方法为Control控件的void WndProc(ref Message m)方法,该方法用于接收任何发送到该控件的windows消息。那么我们就可以通过重写该方法来截获绘制窗体标题栏和边框的消息了。

找到了截获windows消息的接口,那么就需要知道哪些windows消息会引起窗体标题栏和边框的重绘。使用工具SPY++查看消息,发现windows消息WM_NCPAINT(0x85)和WM_NCACTIVATE(0x86),WM_NCRBUTTONDOWN(0x00A4),WM_SETCURSOR(0x0020),WM_NCLBUTTONUP(0x00A2),WM_NCLBUTTONDOWN(0xA1)等会重绘标题栏和边框。其中WM_NCPAINT和WM_NCACTIVATE会引起重绘标题栏和边框,消息WM_NCRBUTTONDOWN会触发标题栏的右键菜单,截获该消息可以自定义标题栏的右键菜单;其他消息会引起ConrtolBox(最小化,最大化,关闭按钮区域)的重绘。因此我们可以从截获这些消息入手。如下为WndProc方法的结构:

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using System.Diagnostics;namespace CaptionBox {public class ThemeForm : Form {#region private structsstruct _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;};#endregion#region constantsconst 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#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 _RECT 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 default constructorpublic ThemeForm() {Text = "ThemeForm1";CloseButtonImage = Properties.Resources.close.ToBitmap();CloseButtonHoverImage = Properties.Resources.close2.ToBitmap();CloseButtonPressDownImage = Properties.Resources.close2.ToBitmap();MaximumButtonImage = Properties.Resources.max.ToBitmap();MaximumButtonHoverImage = Properties.Resources.max2.ToBitmap();MaximumButtonPressDownImage = Properties.Resources.max2.ToBitmap();MaximumNormalButtonImage = Properties.Resources.maxnorm.ToBitmap();MaximumNormalButtonHoverImage = Properties.Resources.maxnorm2.ToBitmap();MaximumNormalButtonPressDownImage = Properties.Resources.maxnorm2.ToBitmap();MinimumButtonImage = Properties.Resources.min.ToBitmap();MinimumButtonHoverImage = Properties.Resources.min2.ToBitmap();MinimumButtonPressDownImage = Properties.Resources.min2.ToBitmap();HelpButtonImage = Properties.Resources.help.ToBitmap();HelpButtonHoverImage = Properties.Resources.help2.ToBitmap();HelpButtonPressDownImage = Properties.Resources.help2.ToBitmap();CaptionColor = Brushes.White;CaptionBackgroundColor = Color.DimGray;SetClassLong(this.Handle, GCL_STYLE, GetClassLong(this.Handle, GCL_STYLE) | CS_DropSHADOW); //API函数加载,实现窗体边框阴影效果
        }#endregion[DefaultValue("")][Browsable(true)][Category("ControlBox")]public virtual ContextMenuStrip CaptionContextMenu { get; set; }protected virtual void OnCaptionContextMenu(int x, int y) {if (this.CaptionContextMenu != null)this.CaptionContextMenu.Show(x, y);}#region properties[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")][DesignOnly(true)]public Brush CaptionColor { get; set; }[Category("CaptionColor")][Description("The color of caption.")][DisplayName("CaptionBackgroundColor")][DefaultValue(typeof(Color), "Black")][DesignOnly(true)]public Color CaptionBackgroundColor { get; set; }#endregion#region help methodsprivate _NonClientSizeInfo GetNonClientInfo(IntPtr hwnd) {_NonClientSizeInfo info = new _NonClientSizeInfo();info.CaptionButtonSize = SystemInformation.CaptionButtonSize;info.CaptionHeight = SystemInformation.CaptionHeight;switch (this.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;}_RECT areatRect = new _RECT();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) {int titleX;if (this.ShowIcon &&this.FormBorderStyle != System.Windows.Forms.FormBorderStyle.FixedToolWindow &&this.FormBorderStyle != System.Windows.Forms.FormBorderStyle.SizableToolWindow) {Size iconSize = SystemInformation.SmallIconSize;g.DrawIcon(this.Icon, new Rectangle(new Point(ncInfo.BorderSize.Width, ncInfo.BorderSize.Height + (ncInfo.CaptionHeight - iconSize.Height) / 2), iconSize));titleX = ncInfo.BorderSize.Width + iconSize.Width + ncInfo.BorderSize.Width;} else {titleX = ncInfo.BorderSize.Width;}SizeF captionTitleSize = g.MeasureString(this.Text, SystemFonts.CaptionFont);g.DrawString(this.Text, SystemFonts.CaptionFont, CaptionColor,new RectangleF(titleX,(ncInfo.BorderSize.Height + ncInfo.CaptionHeight - captionTitleSize.Height) / 2,ncInfo.CaptionRect.Width - ncInfo.BorderSize.Width * 2 - SystemInformation.MinimumWindowSize.Width,ncInfo.CaptionRect.Height), StringFormat.GenericTypographic);}private void DrawBorder(Graphics g, _NonClientSizeInfo ncInfo, Brush background, bool active) {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(ncInfo.BorderSize.Width, ncInfo.ClientRect.Height + ncInfo.CaptionHeight + ncInfo.BorderSize.Height));Rectangle borderRight = new Rectangle(ncInfo.Rect.Left + ncInfo.Rect.Width - ncInfo.BorderSize.Width,ncInfo.Rect.Top + ncInfo.BorderSize.Height,ncInfo.BorderSize.Width,ncInfo.ClientRect.Height + ncInfo.CaptionHeight + ncInfo.BorderSize.Height);Rectangle borderBottom = new Rectangle(ncInfo.Rect.Left + ncInfo.BorderSize.Width,ncInfo.Rect.Top + ncInfo.Rect.Height - ncInfo.BorderSize.Height,ncInfo.Rect.Width - ncInfo.BorderSize.Width * 2,ncInfo.Rect.Height);//Rectangle leftbottom = new Rectangle(new Point(ncInfo.Rect.Location.X, ncInfo.Rect.Height - ncInfo.BorderSize.Width * 2),//    new Size(ncInfo.BorderSize.Width * 2, ncInfo.BorderSize.Width * 2));//g.FillPie(Brushes.Red, leftbottom, 90, 180);//g.FillRectangle(Brushes.Red, leftbottom);// top border
            g.FillRectangle(background, borderTop);// left border
            g.FillRectangle(background, borderLeft);// right border
            g.FillRectangle(background, borderRight);// bottom border
            g.FillRectangle(background, borderBottom);}private void DrawCaption(IntPtr hwnd, bool active) {IntPtr dc;Graphics g;Size iconSize;_NonClientSizeInfo ncInfo;Brush backgroundColor = new SolidBrush(CaptionBackgroundColor);Brush foregroundColor = CaptionColor;iconSize = SystemInformation.SmallIconSize;dc = GetWindowDC(hwnd);ncInfo = GetNonClientInfo(hwnd);g = Graphics.FromHdc(dc);g.FillRectangle(backgroundColor, ncInfo.CaptionRect);DrawBorder(g, ncInfo, backgroundColor, active);DrawTitle(g, ncInfo, active);DrawControlBox(g, ncInfo, backgroundColor, this.ControlBox, this.MaximizeBox, this.MinimizeBox, this.HelpButton);g.Dispose();ReleaseDC(hwnd, dc);}private void DrawControlBox(Graphics g, _NonClientSizeInfo info, Brush background, bool closeBtn, bool maxBtn, bool minBtn, bool helpBtn) {if (this.ControlBox) {int closeBtnPosX = info.CaptionRect.Left + 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 (this.MaximizeBox || this.MinimizeBox) {if (this.FormBorderStyle != System.Windows.Forms.FormBorderStyle.FixedToolWindow &&this.FormBorderStyle != System.Windows.Forms.FormBorderStyle.SizableToolWindow) {if (this.WindowState == FormWindowState.Maximized) {g.DrawImage(MaximumNormalButtonImage, maxRect);} else {g.DrawImage(MaximumButtonImage, maxRect);}g.DrawImage(MinimumButtonImage, minRect);}} else if (this.HelpButton) {if (this.FormBorderStyle != System.Windows.Forms.FormBorderStyle.FixedToolWindow &&this.FormBorderStyle != System.Windows.Forms.FormBorderStyle.SizableToolWindow) {g.DrawImage(HelpButtonImage, maxRect);}}}}#endregion#region Major method WndProcprivate int LOBYTE(long p) { return (int)(p & 0x0000FFFF); }private int HIBYTE(long p) { return (int)(p >> 16); }protected override void WndProc(ref Message m) {if (this.FormBorderStyle != System.Windows.Forms.FormBorderStyle.None) {switch (m.Msg) {case WM_NCPAINT:DrawCaption(m.HWnd, Form.ActiveForm == this);return;case WM_NCACTIVATE:DrawCaption(m.HWnd, m.WParam.ToInt32() > 0);return;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 = this.PointToClient(new Point(posX, posY));if (this.CaptionContextMenu != null) {this.CaptionContextMenu.Show(posX, posY);return;}}break;}case WM_SETCURSOR:if (this.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);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);g.FillRectangle(backgroundColor, btnRect);g.FillRectangle(backgroundColor, maxRect);g.FillRectangle(backgroundColor, minRect);if (posX != HTCLOSE) {g.DrawImage(CloseButtonImage, btnRect);} else if (MouseButtons != System.Windows.Forms.MouseButtons.Left) {g.DrawImage(CloseButtonHoverImage, btnRect);} else {g.DrawImage(CloseButtonPressDownImage, btnRect);}if (this.MaximizeBox || this.MinimizeBox) {if (this.FormBorderStyle != System.Windows.Forms.FormBorderStyle.FixedToolWindow &&this.FormBorderStyle != System.Windows.Forms.FormBorderStyle.SizableToolWindow) {if (this.WindowState == FormWindowState.Maximized) {if (this.MaximizeBox) {if (posX != HTMAXBUTTON) {g.DrawImage(MaximumNormalButtonImage, maxRect);} else if (MouseButtons != System.Windows.Forms.MouseButtons.Left) {g.DrawImage(MaximumNormalButtonHoverImage, maxRect);} else {g.DrawImage(MaximumNormalButtonPressDownImage, maxRect);}} else {g.DrawImage(MaximumNormalButtonImage, maxRect);}} else {if (this.MaximizeBox) {if (posX != HTMAXBUTTON) {g.DrawImage(MaximumButtonImage, maxRect);} else if (MouseButtons != System.Windows.Forms.MouseButtons.Left) {g.DrawImage(MaximumButtonHoverImage, maxRect);} else {g.DrawImage(MaximumButtonPressDownImage, maxRect);}} else {g.DrawImage(MaximumButtonImage, maxRect);}}if (this.MinimizeBox) {if (posX != HTMINBUTTON) {g.DrawImage(MinimumButtonImage, minRect);} else if (MouseButtons != System.Windows.Forms.MouseButtons.Left) {g.DrawImage(MinimumButtonHoverImage, minRect);} else {g.DrawImage(MinimumButtonPressDownImage, minRect);}} else {g.DrawImage(MinimumButtonImage, minRect);}}} else if (this.HelpButton) {if (this.FormBorderStyle != System.Windows.Forms.FormBorderStyle.FixedToolWindow &&this.FormBorderStyle != System.Windows.Forms.FormBorderStyle.SizableToolWindow) {if (posX != HTHELP) {g.DrawImage(HelpButtonImage, maxRect);} else if (MouseButtons != System.Windows.Forms.MouseButtons.Left) {g.DrawImage(HelpButtonHoverImage, maxRect);} else {g.DrawImage(HelpButtonPressDownImage, maxRect);}}}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 (this.MaximizeBox) {m.Msg = WM_SYSCOMMAND;if (this.WindowState == FormWindowState.Maximized) {m.WParam = new IntPtr(SC_RESTORE);} else {m.WParam = new IntPtr(SC_MAXIMIZE);}}break;case HTMINBUTTON:if (this.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 (this.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);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 (this.MaximizeBox || this.MinimizeBox) {if (this.FormBorderStyle != System.Windows.Forms.FormBorderStyle.SizableToolWindow &&this.FormBorderStyle != System.Windows.Forms.FormBorderStyle.FixedToolWindow) {if (this.WindowState == FormWindowState.Maximized) {if (wp == HTMAXBUTTON && this.MaximizeBox) {minBtnPosX = maxBtnPosX - ncInfo.CaptionButtonSize.Width;g.DrawImage(MaximumNormalButtonPressDownImage, maxRect);ret = true;} else {g.DrawImage(MaximumNormalButtonImage, maxRect);}} else {if (wp == HTMAXBUTTON && this.MaximizeBox) {minBtnPosX = maxBtnPosX - ncInfo.CaptionButtonSize.Width;g.DrawImage(MaximumButtonPressDownImage, maxRect);ret = true;} else {g.DrawImage(MaximumButtonImage, maxRect);}}if (wp == HTMINBUTTON && this.MinimizeBox) {g.DrawImage(MinimumButtonPressDownImage, minRect);ret = true;} else {g.DrawImage(MinimumButtonImage, minRect);}}} else if (this.HelpButton) {if (this.FormBorderStyle != System.Windows.Forms.FormBorderStyle.FixedToolWindow &&this.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;}}base.WndProc(ref m);}#endregion}
}

运行效果:

原文及源码下载地址:http://blog.csdn.net/guangboo/article/details/8264293

【转】【C#】C#重绘windows窗体标题栏和边框相关推荐

  1. 重绘Winform窗体

    本文转载自:http://www.cnblogs.com/encoding/p/5603080.html 按照惯例,先来几张样例图(注:为了展示窗口阴影效果,截图范围向外扩展了些,各位凭想象吧). 还 ...

  2. WPF-隐藏窗体标题栏和边框

    方法一 AllowsTransparency="True" WindowStyle="None" 缺点:使用该方法会导致标题栏无法被拖动,可以自我添加boder ...

  3. C# Windows 窗体的.Net 框架绘图技术

    当编写一个典型的Windows 窗体程序时,窗体和控件的绘制.效果等操作是不需要特别加以考虑的.这是为什么呢?因为通过使用 .Net 框架,开发人员可以拖动一系列的控件到窗体上,并书写一些简单的与事件 ...

  4. Java小白画图板的重绘包括谢尔宾斯基三角形和蕨类图像的重绘

    本作者在构造射线的重绘时出现了错误,将会在以后的文章中贴出来... 画板的重绘 当窗体的状态发生改变时,画板上的缓存会自动清空.屏幕上绘制的图像是将窗体中的对象数据从内存中取出来放到缓存中,再绘制的. ...

  5. winform 异步弹窗窗体_玩转控件:重写/重绘Dev中MessageBox弹窗控件

    很久没有更新博客了,本想着直接发一篇<手撕ERP>系列,从控件重写.重绘,到框架搭建,再到部分模块实现+业务的.但是每次动手的时候,都觉得难以下手.直接从数据库设计开始吧,模块设计还没定下 ...

  6. windows重绘机制原理

    一.Windows程序中的绘制和更新 与DOS环境比较,Windows中的应用程序在处理文字和图形绘制时有以下区别: 1.只能在窗口的客户区域绘制文字和图形 2.在窗口上绘制的内容不一定能够保留到程序 ...

  7. 【转】 VC MFC 钩子 实现 自绘 窗体 标题栏 非客户区

    效果: 程序: #if !defined(_LJF_LJFHOOK_H) #define _LJF_LJFHOOK_H #if _MSC_VER > 1000 #pragma once #end ...

  8. VC 实现 自绘 窗体 标题栏 非客户区

    转载自 ljfblog 最终编辑 gh0716 本程序在VC03测试成功,效果, 图片素材:从BC1.bmp到第2页的UR_N.bmp ■■更新■■ 彻底解决最大最小关闭按钮依然显示的问题: 在Win ...

  9. [DForm]我也来做自定义Winform之另类标题栏重绘

    引用:https://www.cnblogs.com/encoding/p/5603080.html 其他下载:https://github.com/dongger/MomoForm 据说得有楔子 按 ...

最新文章

  1. kubernetes创建资源的两种方式
  2. 【bzoj3524】Couriers——主席树
  3. 哪个版本python适用于windows-何种版本的Python适合您
  4. JAVA遇见HTML——JSP篇(JSP内置对象上)
  5. pycharm的安装与python解释器的安装,pip环境变量的配置要不然使用pip时报不是内部命令
  6. BlockChain:《世界经济论坛:区块链将如何重塑金融业?》—20160812—听课笔记
  7. mysql 导入密码_mysql 常用命令导入导出修改root密码
  8. java mathematica_用Java获取Mathematica图像
  9. 抛物线的中点生成算法_零基础学习梯度下降算法
  10. 商用VR新时代已来临?IDC《VR产业研究白皮书》给出答案
  11. LeetCode刷题(20)
  12. jupyter新建文件_初学jupyter,运行,下载,上传导入文件
  13. ngx_http_upstream_module模块学习笔记
  14. excel2016 android,Microsoft Excel
  15. matplotlb之柱形图与盒形图
  16. 用C语言学习高中数学:补集
  17. 数据挖掘导论课后习题答案-第七章
  18. 认识计算机的桌面,电脑桌面的基础知识教程,教你认识电脑桌面
  19. Android Process 'command 'C:\Users\Win\AppData\Local\Android\Sdk\build-t non-zero exit value 1错误解决方案
  20. 计算机网络 一、 IP地址,域名,DNS

热门文章

  1. 访谈计算机操作管理协会(Afcom)首席执行官Jill Eckhaus:数据中心问题出现在何处?...
  2. div布局的几点体会
  3. 【直播回顾】云栖社区特邀专家徐雷Java Spring Boot开发实战系列课程(第19讲):Java Spring Cloud微服务架构模式与开发实战...
  4. [VNC] 分辨率, 退出全屏,
  5. 【数据结构】回顾散列表
  6. 找出两个字符串中最长的相同子字符串
  7. 常用实验资源共享整理 20111026
  8. struts2中报错404 No result defined for action com.jcrj.ahsfjd.ajgl.JdshAction and result input解决方法...
  9. python列表操作:追加元素到列表的代码
  10. Tensorflow BatchNormalization详解:4_使用tf.nn.batch_normalization函数实现Batch Normalization操作...