




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、C#重绘windows窗体标题栏和边框摘要windows桌面应用程序都有标准的标题栏和边框,大部分程序也默认使用这些样式,一些对视觉效果要求较高的程序,如QQ, MSN,迅雷等聊天工具的样式则与传统的windows程序大不相同,其中迅雷还将他们的BOLT界面引擎开放,使得大家也可以创建类似迅雷一样的界面。 那么这些软件的界面是怎样实现的呢,使用C#是否也可以实现类似界面?重绘方式常见的自定义标题栏和边框的方式有两种,一种是隐藏标题栏和边框(称为非客户区),然后在客户区(可以放置控件的空间)使用一些常用的控件和图片来表示边 框,这种方式较简单而麻烦,但如标题栏的拖动,边框的拖拽来改变窗体大小等效
2、果,则有需要重新实现,另外有些客户区的鼠标事件,控件布局等也需要注意调 整;另一种则是大部分软件实现方式,也较难一些;它利用windows的消息机制,截获windows消息,从而改变消息的行为。即windows的一些 消息,会引起窗体绘制或重绘标题栏和边框的行为,因此只要结果这部分消息,然后开发人员自己处理绘制过程,并忽略默认行为,从而达到自定义的目的。C#绘制接口windows消息对于C#开发新手来说较生疏,原因是.net已经将windows消息机制进行了封装,使得我们很难发现windows消息的踪迹,其 实它是以另一个身份存在着-事件。如控件的OnClick,Mouse等事件,都是对win
3、dows消息的封装,这样的目的更容易理解,和运 用。.net提供了处理消息的接口,常用的方法为Control控件的void WndProc(ref Message m)方法,该方法用于接收任何发送到该控件的windows消息。那么我们就可以通过重写该方法来截获绘制窗体标题栏和边框的消息了。找到了截获windows消息的接口,那么就需要知道哪些windows消息会引起窗体标题栏和边框的重绘。使用工具SPY+查看消息,发现 windows消息WM_NCPAINT(0x85)和 WM_NCACTIVATE(0x86),WM_NCRBUTTONDOWN(0x00A4),WM_SETCURSOR(0x0
4、020),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 S
5、ystem.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 in
6、t 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;
7、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
8、= 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 = 0x021
9、4; 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
10、_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 HTCA
11、PTION = 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 w
12、indows 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 i
13、nt 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); #e
14、ndregion #region default constructor public ThemeForm() Text = "ThemeForm1" CloseButtonImage = Properties.Resources.close.ToBitmap(); CloseButtonHoverImage = Properties.Resources.close2.ToBitmap(); CloseButtonPressDownImage = Properties.Resources.close2.ToBitmap(); MaximumButtonImage = Pro
15、perties.Resources.max.ToBitmap(); MaximumButtonHoverImage = Properties.Resources.max2.ToBitmap(); MaximumButtonPressDownImage = Properties.Resources.max2.ToBitmap(); MaximumNormalButtonImage = Properties.Resources.maxnorm.ToBitmap(); MaximumNormalButtonHoverImage = Properties.Resources.maxnorm2.ToBi
16、tmap(); MaximumNormalButtonPressDownImage = Properties.Resources.maxnorm2.ToBitmap(); MinimumButtonImage = Properties.Resources.min.ToBitmap(); MinimumButtonHoverImage = Properties.Resources.min2.ToBitmap(); MinimumButtonPressDownImage = Properties.Resources.min2.ToBitmap(); HelpButtonImage = Proper
17、ties.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_STY
18、LE) | 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.CaptionCon
19、textMenu.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 imag
20、e 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")
21、 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") Descri
22、ption("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("
23、;MaximumButtonPressDownImage") DesignOnly(true) public Image MaximumButtonPressDownImage get; set; Category("ControlBox") Description("Maximum Normal button image in control box.") DisplayName("MaximumNormalButtonImage") DesignOnly(true) public Image MaximumNormalB
24、uttonImage 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(&
25、quot;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.") Dis
26、playName("MinimumButtonImage") DesignOnly(true) public Image MinimumButtonImage get; set; Category("ControlBox") Description("Minimum button hover image in control box.") DisplayName("MinimumButtonHoverImage") DesignOnly(true) public Image MinimumButtonHoverIm
27、age 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 b
28、utton 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
29、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") Descript
30、ion("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&
31、quot;) 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 = System
32、Information.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 Sy
33、stem.Windows.Forms.FormBorderStyle.FixedSingle: info.BorderSize = SystemInformation.FixedFrameBorderSize; break; case System.Windows.Forms.FormBorderStyle.FixedToolWindow: info.BorderSize = SystemInformation.FixedFrameBorderSize; info.CaptionButtonSize = SystemInformation.ToolWindowCaptionButtonSize
34、; 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.ToolWindowCa
35、ptionButtonSize; 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
36、- 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)
37、; 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(
38、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.Small
39、IconSize; 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 captionTitle
40、Size = 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 - SystemInformatio
41、n.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.R
42、ect.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
43、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.Widt
44、h, 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,
45、 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
46、 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.SmallIcon
47、Size; 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)
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年软件设计师考试应对措施及试题及答案
- 行政法学人才培养的方向及问题试题及答案
- 信息处理技术真正重要考点试题及答案
- 网络安全审计的实施策略试题及答案
- 行政法学形势变化试题及答案
- 软件测试流程与工具试题及答案
- 网络环境与管理模式的风险试题及答案
- 跨界创新在经济转型中的作用研究试题及答案
- 公司生产工作计划推动生产检验标准化与检验员培训
- 高考作文世代传承的试题与答案
- 建筑企业安全生产事故报告及处理制度(4篇)
- 第七章 循证医学课件
- 风电专业考试题库带答案
- 艾滋病职业防护培训
- 教学反思不足之处和改进措施简短
- 舒适化医疗麻醉
- 露营地合伙人合同协议书范本
- 2024年315消费者权益保护知识竞赛题库及答案(完整版)
- 2024秋期国家开放大学《可编程控制器应用实训》一平台在线形考(形成任务1)试题及答案
- 2023年高考真题-地理(河北卷) 含答案
- DB50-T 1649-2024 餐饮业菜品信息描述规范
评论
0/150
提交评论