【转】【C#】C#重绘windows窗体标题栏和边框
摘要
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 structs 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;
}; #endregion #region constants 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 = ;
const int WMSZ_BOTTOMLEFT = ;
const int WMSZ_BOTTOMRIGHT = ;
const int WMSZ_LEFT = ;
const int WMSZ_RIGHT = ;
const int WMSZ_TOP = ;
const int WMSZ_TOPLEFT = ;
const int WMSZ_TOPRIGHT = ; // 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 = ;
const int HTCLOSE = ;
const int HTHELP = ;
const int HTMAXBUTTON = ;
const int HTMINBUTTON = ;
const int HTTOP = ; const int SM_CYBORDER = ;
const int SM_CXBORDER = ;
const int SM_CYCAPTION = ; const int CS_DropSHADOW = 0x20000;
const int GCL_STYLE = (-); #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 constructor public 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 methods private _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 * ,
height - info.CaptionHeight - info.BorderSize.Height * ); 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) / ), 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) / ,
ncInfo.CaptionRect.Width - ncInfo.BorderSize.Width * - 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 * ,
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) / ; 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 WndProc private int LOBYTE(long p) { return (int)(p & 0x0000FFFF); }
private int HIBYTE(long p) { return (int)(p >> ); } 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() > );
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) / ; 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) / ;
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窗体标题栏和边框的更多相关文章
- 窗体背景的绘制(Windows窗体每次都会重绘其窗体背景,所以我们可以通过拦截窗体重绘背景的消息(WM_ERASEBKGND),并自定义方法来实现重绘窗体背景)
核心思想:由于Windows窗体每次都会重绘其窗体背景,所以我们可以通过拦截窗体重绘背景的消息(WM_ERASEBKGND),并自定义方法来实现重绘窗体背景.通过TImage组件也可以实现,但是重写W ...
- 重绘Winform窗体
本文转载自:http://www.cnblogs.com/encoding/p/5603080.html 按照惯例,先来几张样例图(注:为了展示窗口阴影效果,截图范围向外扩展了些,各位凭想象吧). 还 ...
- Windows开发进阶之VC++中如何实现对话框的界面重绘
技术:Windows 系统+Visual studio 2008 概述 应用程序界面是用户与应用程序之间的交互的桥梁和媒介,用户界面是应用程序中最重要的组成部分,也是最为直观的视觉体现.对用户而言 ...
- Windows 窗体的.Net 框架绘图技术
当编写一个典型的Windows 窗体程序时,窗体和控件的绘制.效果等操作是不需要特别加以考虑的.这是为什么呢?因为通过使用 .Net 框架,开发人员可以拖动一系列的控件到窗体上,并书写一些简单的与事件 ...
- 使用WIN32汇编语言实现一个基本windows窗体的过程分析
一个常规的windows窗体一般都是一些一样的构造.你假设想要更改一些个性化的设置,你能够在这个一般的模板伤添砖加瓦.构造自己比較喜欢的类型.下边就分析一下一般的windows窗体的一般模板. 一. ...
- 深入Windows窗体原理及控件重绘技巧
之前有学MFC的同学告诉我觉得Windows的控件重绘难以理解,就算重绘成功了还是有些地方不明白,我觉得可能很多人都有这样的问题,在这里我从Windows窗体的最基本原理来讲解,如果你有类似的疑惑希望 ...
- c#winform自定义窗体,重绘标题栏,自定义控件学习
c#winform自定义窗体,重绘标题栏 虽然现在都在说winform窗体太丑了,但是我也能尽量让桌面应用程序漂亮那么一点点话不多说,先上图 重绘标题栏先将原生窗体设置成无边框,FormBoderSt ...
- [DForm]我也来做自定义Winform之另类标题栏重绘
据说得有楔子 按照惯例,先来几张样例图(注:为了展示窗口阴影效果,截图范围向外扩展了些,各位凭想象吧). 还要来个序 其实,很多年没写过Winform了,前端时间在 ...
- 重写OnPaint事件对窗体重绘(显示gif动画) 实例2
/// <summary> /// 可显示Gif 的窗体 /// </summary> public class WinGif : Form { private Image _ ...
随机推荐
- How to load a raster dataset to the raster field in a feature class
A feature class or table can have a raster attribute field to store any raster related to the featur ...
- SQL 查询学生缺考情况
有三个表,如果学生缺考,那么在成绩表中就不存在这个学生的这门课程成绩的记录,写一段SQL语句,检索出每个学生缺考的科目.A 学生表(student)字段1 学生号(s_id)字段2 学生名(s_nam ...
- ubuntu解决arm-linux-gcc no such file的问题
这种情况是因为你的操作系统是Ubuntu 64位的,而交叉编译工具链都是32位执行程序.要成功运行这些交叉编译工具链,需要与这些工具链相关的32位库.安装命令如下:sudo apt-get insta ...
- C语言中的字符和字符串
C语言在中常常出现字符和字符串,而一串字符或者字符串其实就是数组 字符数组的定义 char arr[]={'h','e','l','l','o','\0'}; 而定义字符串: char arr1[]= ...
- 明明已经执行Log.i,偏偏打不出日志
Android内打日志用的当然是Log.i(tag,string),调试时的日志输出可以很快的反映一些问题,方便我们跟进. 但是如果连日志都打不出来了怎么办呢,我今天就遇到了比较坑的问题.项目里别的日 ...
- Android开发者的Git&Github(一)
安装Git: Linux(以Ubuntu为例): sudo apt-get install git-core Windows: 访问网址http://msysgit.github.io/下载安装包 下 ...
- Stack与Heap的区别
申明:这里所说的栈和堆是程序内存管理中的栈和堆,而不是数据结构里的栈和堆. (1)保存的内容不同:栈里保存的是局部变量,而堆里保存的是动态申请的变量. (2)栈里的内存系统自动申请和释放,程序执行出申 ...
- 静态代码检查工具-PMD初学者入门篇
前言: PMD是一款静态代码分析工具,它能够自动检测各种潜在缺陷以及不安全或未优化的代码. PMD更多地是集中在预先检测缺陷上,它提供了高度可配置的丰富规则集,用户可以方便配置对待特定项目使用那些规则 ...
- jQuery 安装方法
在WEB中使用jQuery有两种安装(引入)方式. 1.直接下载jQuery包放置到工程中,然后用js导入的方式连接到WEB页面中 2.利用CDN的公网资源,如百度.新浪等. 访问 http://cd ...
- IOS沙盒Files目录说明和常用操作
Ios沙盒目录清单 1 Documents 用于存储用户生成的文件.其他数据及其他程序不能重新创建的文件,默认文件通过iCloud自动备份.如果不需要iCloud备份,则设置标记 NSURLIsExc ...