![[计算机]NET实现OfficeXP风格的菜单.doc_第1页](http://file.renrendoc.com/FileRoot1/2019-1/5/445d7688-e963-44be-9374-2712ea01f1b8/445d7688-e963-44be-9374-2712ea01f1b81.gif)
![[计算机]NET实现OfficeXP风格的菜单.doc_第2页](http://file.renrendoc.com/FileRoot1/2019-1/5/445d7688-e963-44be-9374-2712ea01f1b8/445d7688-e963-44be-9374-2712ea01f1b82.gif)
![[计算机]NET实现OfficeXP风格的菜单.doc_第3页](http://file.renrendoc.com/FileRoot1/2019-1/5/445d7688-e963-44be-9374-2712ea01f1b8/445d7688-e963-44be-9374-2712ea01f1b83.gif)
![[计算机]NET实现OfficeXP风格的菜单.doc_第4页](http://file.renrendoc.com/FileRoot1/2019-1/5/445d7688-e963-44be-9374-2712ea01f1b8/445d7688-e963-44be-9374-2712ea01f1b84.gif)
![[计算机]NET实现OfficeXP风格的菜单.doc_第5页](http://file.renrendoc.com/FileRoot1/2019-1/5/445d7688-e963-44be-9374-2712ea01f1b8/445d7688-e963-44be-9374-2712ea01f1b85.gif)
已阅读5页,还剩15页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1用C#和VB.NET实现Office XP风格的菜单VS.NET或Office XP中的菜单都是非常漂亮的,反正我很喜欢。可惜VS.NET没1有带制作这种菜单的控件或组件,不知正式版本会不会提供一个模板和向导。至今还记1得刚学计算机语言时自己用Turbo C制作菜单的感受,那些矩形框函数和象素操作的确很迷人,况且那时是如此的流行菜单。 这篇文章中我会介绍有关在Framework SDK Beta 2 中制作自己风格的菜单,所以你最好已安装了Framework SDK Beta 2,VS.NET Beta 2 不一定是必须的。附带的Zip包中的例子都是VS.NET Project的。整个的文章包括三部分:开始我会涉及到在Winform中最基本的一些菜单的概念。然后会有一个以前接触过的有关菜单的例子,它是For Beta 1的。老实说我没有想到Beta1 到Beta2有许多函数和命名空间发生了变化,以前我在Beta1中测试过这个1例子,很顺利。这次在Beta2中会有许多错误,我提供了两个Project,一个是原来的Project的,一个是我修改后For Beta 2的。这种移植很枯燥,但可以很快熟悉新的Beta2的类库和函数,Show出来的菜单还不错,感觉是Office2000风格的菜单。如果你有兴趣可以试一试这个过程,会获益非浅的,这个例子还包括按钮的,原来的作者其实是在Demo控件的“Owner-drawn menus”技术;不过我只对菜单部分感兴趣。最后一部分是制作VS.NET或XP风格的例子,上面那个例子的效果不能使我完全满意,然后我重新写了另外一个,不过我对最后的结果还不是很满意,因为我的没有上一个例子那么完整,例子中我只显示了这个风格的菜单,对于事件响应、状态栏更新、tooltips、菜单的状态(enabled state)等处理都没有考虑,我把这些归结为时间问题,并承诺自己下次把它做得更好。1Framework SDK Beta 2中菜单分成两类一类是普通的菜单叫:MainMenu,在VS.NET的Toolsbox中有这样一个对应的菜单控件,拖下它到你的窗体中,设置一下属性就可以所见所得了,这个版本的比VS.Studio98 系列的要好用和漂亮的多。另一类叫:ContextMenu菜单,也就是常用的弹出菜单。对于VB6来说所有的普通菜单在VS.NET中是可以兼容和自动升级成MainMenu类型的菜单,但对于PopMenu的菜单是不能转换成ContextMenu类型的菜单,你必须自己重新修改代码实现。这里我们主要是针对MainMenu的,其实原理一样。最简单的菜单你可以这样做:using System;using System.Windows.Forms;public class frmVB6 : Form private MainMenu muMain ; / MainMenu public static int Main(string Args) Application.Run(new frmVB6();return 0;public frmVB6() / The following code sets up the form properties.this.Text = Form1;this.Height = 213 + SystemInformation.CaptionHeight;this.Width = 312;this.StartPosition = FormStartPosition.WindowsDefaultLocation;MenuItem mItemFile = new MenuItem() ; mItemFile.Text = &File ; MenuItem mItemExit = new MenuItem() ; mItemExit.Text = E&xit ;muMain = new MainMenu() ; muMain.MenuItems.Add( mItemFile ) ; muMain.MenuItems.Add( mItemExit) ; this.Menu = muMain ; 手工方式保存它为一个.cs文件然后在编译它:csc /t:winexe /r:System.dll /r:System.Windows.Forms.Dll /r:System.Drawing.Dll Form1Menu.csVS.NET下只用New一个新的WinForm项目,然后在默认窗体中放入MainMenu控件,然后设置完属性,F5就可以了,完全不用一行代码。如果要生成一个主菜单和一个菜单的子菜单项目,主要是MenuItems.AddRange的方法,看下面的代码:this.mainMenu1 = new System.Windows.Forms.MainMenu();this.menuItem1 = new System.Windows.Forms.MenuItem();this.menuItem2 = new System.Windows.Forms.MenuItem();this.menuItem3 = new System.Windows.Forms.MenuItem();this.menuItem4 = new System.Windows.Forms.MenuItem();/ mainMenu1this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem this.menuItem1, this.menuItem2);/ menuItem1this.menuItem1.Index = 0;this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem this.menuItem3, this.menuItem4);this.menuItem1.Index = 0 ; this.menuItem1.Text = &File;/ menuItem2this.menuItem2.Index = 1;this.menuItem2.Text = Help;/ menuItem3this.menuItem3.Index = 0;this.menuItem3.Text = Open;this.menuItem3.Click += new System.EventHandler(this.menuItem3_Click);/ menuItem4this.menuItem4.Index = 1;this.menuItem4.Text = Exit;this.menuItem4.Click += new System.EventHandler(this.menuItem4_Click);this.Menu = this.mainMenu1;如代码所示MenuItem1(File)和MenuItem2(Help)被AddRange到MainMenu1中成为了顶级的菜单,MenuItem3(Open)和MenuItem4(Exit)被AddRange到MenuItem1(File)中成为了File菜单下的子菜单项。this.menuItem3.Click += new System.EventHandler(this.menuItem3_Click);表明MenuItem3点击时激发的事件处理程序,一般的事件处理程序象下面这样:private void menuItem3_Click(object sender, System.EventArgs e)MessageBox.Show ( My Click Open ) ; 我们关心的其实是MenuItem,让它用我们的方式画出有VS.NET或XP风格的菜单就可以了,更简单的说就是实现一个MenuItem的继承类,扩展它Draw的部分。好吧,让我们深入一点看看第二部分。2“Owner-drawn menus”技术这个例子是VB.NET语法的.我去掉了和Menu无关的Class,原因是错误太多,你会遇到类库和命名空间的移植性的问题:最多的是Beta1 System.WinForms 和Beta 2 的System.Windows.Froms的命名空间问题;然后是Beta1中的BitAnd 、BitOR等等Bitxxx的函数在Beta2中已去掉了Bit又和VB中一样了(据说Beta1的这项改动遭到了总多VB Fans的投诉,说不能把VB也C化,Bit是什么东东),这样你需要把这类函数改掉;然后是NameObjectCollectionBase从原来的system.collections中删除了,Beta2放在system.collections.specialized 中,真的有些昏倒,开始我还以为Beta2中删除了这个类。最后是一些Overrides和 Overloads的问题,具体的看VS.NET或Framework SDK Beta 2编译时的提示就可以了,这方面MS做得不错,Task list中告诉你具体得建议,照做就是了。具体一点你可以在Framework SDK Beta 2安装目录的Doc目录中找到这两个文件,这是从Beta1移植到Beta2上不错的指导文件:APIChangesBeta1toBeta2.htm 和Change List - Beta1 to Beta2.doc 特别是这个doc文件洋洋洒洒90多页,但很有帮助。希望你还能在排除所有的错误之后保持清醒,找到最核心有用的代码,来分析。主要是CActionMenu.vb,焦点在OnMeasureItem和OnDrawItem这两个函数或说事件处理程序上。OnMeasureItem主要是处理MenuItem的ItemHeight和ItemWidth的,从它传的MeasureItemEventArgs参数数就知道。OnDrawItem主要是如何画菜单的问题。关键字Overrides表明我们要在子类中重新定义MenuItem中的这两个方法。从56行到58行是OnMeasureItem函数:Protected Overrides Sub OnMeasureItem(ByVal e As System.Windows.Forms.MeasureItemEventArgs)If Me.Action.Caption = - Thene.ItemHeight = 5Elsee.ItemHeight = 20End IfDim fs As FontStyleIf Me.DefaultItem = True Then fs = fs Or FontStyle.BoldDim fnt As New Font(Tahoma, 8, fs)Dim sf As SizeF = e.Graphics.MeasureString(Me.Action.Caption, fnt)fnt.Dispose()e.ItemWidth = CInt(sf.Width) + 20End SubMeasureItemEventArgs提供4个属性Graphis、Index、ItemHeight和ItemWidth。Me相当于C或Java的this关键字。fnt.Dispose()中Dispose是一个很有意思的函数调用,在以往的Windows编程中象字体、画笔等许多资源都希望快使用快释放,这个语句是用来控制GC(garbage collection)的,意思是我已使用完了这个设备或资源,GC你可以收回了。从70到146行是有关OnItemDraw函数的:Protected Overrides Sub OnDrawItem(ByVal e As System.Windows.Forms.DrawItemEventArgs) colors, fontsDim clrBgIcon, clrBgText, clrText As Color, fs As FontStyle, fnt As FontDim b As SolidBrush, p As PenDim fEnabled As Boolean = Not CType(e.State And DrawItemState.Disabled, Boolean)Dim fSelected As Boolean = CType(e.State And DrawItemState.Selected, Boolean)Dim fDefault As Boolean = CType(e.State And DrawItemState.Default, Boolean)Dim fBreak As Boolean = (Me.Action.Caption = -)If fEnabled And fSelected And Not fBreak ThenclrBgIcon = Color.SilverclrBgText = Color.WhiteclrText = Color.Bluefs = fs Or FontStyle.UnderlineElseclrBgIcon = Color.GrayclrBgText = Color.SilverclrText = Color.BlackEnd IfIf Not fEnabled ThenclrText = Color.WhiteEnd IfIf fDefault Thenfs = fs Or FontStyle.BoldEnd Iffnt = New Font(Tahoma, 8, fs) total background (partly to remain for icon)b = New SolidBrush(clrBgIcon)e.Graphics.FillRegion(b, New Region(e.Bounds)b.Dispose() icon?If Not Me.Action.ActionList Is Nothing ThenDim il As ImageList = Me.Action.ActionList.ImageListIf Not il Is Nothing ThenDim index As Integer = Me.Action.ImageIf index -1 And index 0;if (selected | (state & DrawItemState.HotLight) 0) if (toplevel & selected) / draw toplevel, selected menuitemg.FillRectangle(new SolidBrush(ibgcolor), bounds);ControlPaint.DrawBorder3D(g, bounds.Left, bounds.Top, bounds.Width, bounds.Height, Border3DStyle.Flat, Border3DSide.Top | Border3DSide.Left | Border3DSide.Right); else / draw menuitem, selected OR toplevel, hotlightedg.FillRectangle(new SolidBrush(sbcolor), bounds);g.DrawRectangle(new Pen(sbbcolor), bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1); else if (!toplevel) / draw menuitem, unselectedg.FillRectangle(new SolidBrush(ibgcolor), bounds);bounds.X += SystemInformation.SmallIconSize.Width + 5;bounds.Width -= SystemInformation.SmallIconSize.Width + 5;g.FillRectangle(new SolidBrush(bgcolor), bounds); else / draw toplevel, unselected menuitemg.FillRectangle(SystemBrushes.Menu, bounds);public void DrawMenuText(Graphics g, Rectangle bounds, string text, string shortcut, bool enabled, bool toplevel, DrawItemState state)StringFormat stringformat = new StringFormat();stringformat.HotkeyPrefix = (state & DrawItemState.NoAccelerator) 0) ? HotkeyPrefix.Hide : HotkeyPrefix.Show;int textwidth = (int)(g.MeasureString(text, SystemInformation.MenuFont).Width);int x = toplevel ? bounds.Left + (bounds.Width - textwidth) / 2: bounds.Left + TEXTSTART;int y = bounds.Top + 2;Brush brush = null;if (!enabled)brush = new SolidBrush(Color.FromArgb(120, SystemColors.MenuText);elsebrush = new SolidBrush(Color.Black);g.DrawString(text, SystemInformation.MenuFont, brush, x, y, stringformat);g.DrawString(shortcut, SystemInformation.MenuFont, brush, bounds.Left + 130, bounds.Top + 2, stringformat);MenuItemStyleDrawer就是那个公用的接口类,无论普通风格、Office2000还是VS.NET风格都要实现自己方式的接口,这个接口包括DrawCheckmark、DrawIcon、DrawMenuText、DrawBackground、DrawSeparator等函数,可以实现菜单项需要的各种函数。完成这部分后可以从MenuItem继承一个子类来象第二部分一样处理了。看下面的代码,具体考察一下熟悉的OnMeasureItem和OnDrawItem:protected override void OnMeasureItem(MeasureItemEventArgs e)base.OnMeasureItem(e);/ make shortcut text 省略这部分代码。if (menustyle != IconMenuStyle.Standard) if (Text = -) e.ItemHeight = 8;e.ItemWidth = 4;return;int textwidth = (int)(e.Graphics.MeasureString(Text + shortcuttext, SystemInformation.MenuFont).Width);e.ItemHeight = SystemInformation.MenuHeight;if (Parent = Parent.GetMainMenu()e.ItemWidth = textwidth - 5; / 5 is a magic number elsee.ItemWidth = Math.Max(160, textwidth + 50);IconMenuStyle.Standard是个enum表明是普通风格、Office2000或是VS。NET的风格。这部分和我们第二部分看到的没有什么不同。protected override void OnDrawItem(DrawItemEventArgs e)base.OnDrawItem(e);Graphics g = e.Graphics;Rectangle bounds = e.Bounds;bool selected = (e.State & DrawItemState.Selected) 0;bool toplevel = (Parent = Parent.GetMainMenu();bool hasicon = Icon != null;style.DrawBackground(g, bounds, e.State, toplevel, hasicon);if (hasicon)style
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年天津市宝坻区事业单位招聘39人笔试备考题库及参考答案详解
- 纺织服饰创意设计创作规定
- 水利工程水质监测规定
- 楼盘销售渠道营销计划制定
- 人身保险价格制度
- 嵌入式系统模块化设计原则
- 冲床模具设计手册
- 离婚后子女抚养权及财产分割执行细则协议
- 煤矿开采承包合同及地质勘查服务协议
- 知识产权归属与保密协议范本(适用于软件开发)
- 制鞋工艺流程
- 土石方工程运输合同
- 国际伤口治疗师汇报
- 《电工基础(第2版)》中职全套教学课件
- 河道清淤与水生态恢复方案
- 2024-2025大学英语考试六级汉译英中英对照
- 铂类化疗药物配置
- 2024-2025学年广东省深圳实验学校高中园高一(上)第一次段考数学试卷(含答案)
- 2024-2025学年天津市和平区双菱中学七年级(上)第一次月考数学试卷
- ISO9001-2015质量管理体系内审培训课件
- 《无线电失效程序》课件
评论
0/150
提交评论