菜单(Menu)是程序界面的重要架构部件自从有了可视化编程工具使用其中的菜单编辑器就可以方便快捷的编辑设计菜单但要想制作出个性化的菜单哪怕对菜单项的任何改变如改变菜单的字体类型大小等只使用菜单编辑器是无法完成了可视化编程工具Visual 也是如此本文的主要内容就是介绍利用Visual Basic Net手工绘制个性化菜单的实现方法
一.简介Net Frame Work SDK 为在VBNet绘制菜单提供的工具
Net Frame Work SDK为Visual Basic Net实现个性化菜单提供了许多工具其中最重要是二个事件及其参数DrawItem事件和其中的DrawItemEventArgs参数MeasureItem事件和其中的MeasureItemEventArgs参数
DrawItem事件和其中的DrawItemEventArgs参数
DrawItem事件是当菜单项的OwnerDraw属性设置为True并且发出绘制菜单项的请求时才发生个性化菜单制作的处理方法就是在此事件中完成的在DrawItem事件处理程序中将接收一个 DrawItemEventArgs类型的参数它包含与此事件相关的数据这些数据对绘制菜单是很重要的表是DrawItemEventArgs类型参数提供特定于此事件的信息
属性 说明
BackColor 获取所绘制的项的背景色
Bounds获取表示所绘制项的边界的矩形
Font 获取分配给所绘制项的字体
ForeColor 获取所绘制项的前景色
Graphics 获取要在其上绘制项的图形表面
Index获取所绘制项的索引值
State 获取所绘制项的状态
表DrawItemEventArgs类型参数提供DrawItem事件特定的信息
MeasureItem事件和其中的MeasureItemEventArgs参数
触发MeasureItem事件必须将菜单项的OwnerDraw属性设置为True个性化菜单制作可通过此事件来获取设定菜单项的大小等MeasureItem事件处理程序中接收一个MeasureItemEventArgs类型的参数此参数对获取设定菜单项的大小是非常重要的表是MeasureItemEventArgs类型参数提供MeasureItem事件的特定信息
属性说明
Graphics获取要测量的Graphics对象
Index 获取设置需要有高度和宽度的项索引
ItemHeight获取设置由Index指定的项高度
ItemWidth获取设置由Index指定的项
表是MeasureItemEventArgs类型参数提供MeasureItem事件的特定信息
二.本文介绍程序的设计调试运行的软件环境
()微软公司视窗服务器版
()Visual Studio Net正式版Net Framework SDK版本号
三.循序渐进绘制自己的菜单
为了加深理解我们用菜单编辑器设计一个简单的菜单然后在此基础上加上个性化定制重新绘制个性化的菜单以下步骤就是利用Visual Studio的菜单编辑器制作一个简单的菜单
启动Visual Studio Net
选择菜单【文件】|【新建】|【项目】后弹出【新建项目】对话框
将【项目类型】设置为【Visual Basic项目】
将【模板】设置为【Windows应用程序】
在【名称】文本框中输入【Visual Basic Net编程之DIY自己画菜单】
在【位置】的文本框中输入【E:\项目】然后单击【确定】按钮这样在E:\VSNET项目目录中就产生了名称为Visual Basic Net编程之DIY自己画菜单的文件夹并在里面创建了名称为Visual Basic Net编程之DIY自己画菜单的项目文件
把Visual Studio Net的当前窗口切换到【Formvb(设计)】窗口并从【工具箱】中的【Windows窗体组件】选项卡中往Form窗体中拖入下列组件一个MainMenu组件名称为MainMenu
选中MainMenu组件单击鼠标右键在弹出的菜单中选择编辑菜单并按照图所示界面设计菜单
图【Visual Basic Net编程之DIY自己画菜单】项目设计界面之一
此时保存上述步骤并单击快捷键F则得到图所示界面
图【Visual Basic Net编程之DIY自己画菜单】运行界面之一
这样通过菜单编辑器就完成了一个非常普通的菜单下面就对此菜单进行改造在改造之前要先设定项目中的三个MenuItem类实例的OwnerDraw属性值为True因为只有此属性值为True才会触发绘制菜单时所需要的DrawItem事件和MeasureItem事件之后再在上面项目的基础上执行下一步操作
把Visual 的当前窗口切换到FormVB的代码编辑窗口并在InitializeComponent过程之后添加下列代码下列代码是绘制文件菜单项其作用是改变文件菜单项的字体大小和菜单项的其具体的绘制方法请参考下列代码中的注释
Private Sub MenuItem_DrawItem ( ByVal sender As Object ByVal e As SystemWindowsFormsDrawItemEventArgs ) Handles MenuItemDrawItem
Dim rfBound As RectangleF = New RectangleF ( eBoundsX eBoundsY eBoundsWidth eBoundsHeight )
根据DrawItemEventArgs参数获得菜单项矩形区域并存储到RectangleF类型实例中
Dim rfBound As Rectangle = New Rectangle ( eBoundsX eBoundsY eBoundsWidth eBoundsHeight )
根据DrawItemEventArgs参数获得菜单项矩形区域并存储到Rectangle类型实例中
Rectangle类型实例和RectangleF类型实例差不多但在后面代码中绘制菜单的函数是有区别的
eGraphicsFillRectangle(New SolidBrush(ColorLightGreen) rfBound)
以LightGreen色彩填充MenuItem菜单项对应的矩形区域
Dim s As MenuItem = CType ( sender MenuItem )
Dim s As String = sText
获得MenuItem菜单项的名称
Dim sfTemp As StringFormat = New StringFormat ( )
sfTempAlignment = StringAlignmentCenter
设定要画的菜单名称的对齐方式中间对齐
eGraphicsDrawString ( s New Font ( 宋体 FontStyleBold ) New SolidBrush ( ColorBlack ) rfBound sfTemp )
以中间对齐方式指定字体大小在指定的矩形区域重画菜单
If eState = ( DrawItemStateNoAccelerator Or DrawItemStateSelected ) Then
根据菜单项的当前绘制状态来绘制菜单项
eGraphicsFillRectangle ( New SolidBrush ( ColorLightYellow ) rfBound )
对菜单项所在的矩形区域进行色彩填充
eGraphicsDrawString ( s New Font ( 宋体 FontStyleBold ) New SolidBrush ( ColorBlack ) rfBound sfTemp )
对菜单项名称绘制
End If
eDrawFocusRectangle ( )
在 DrawItemEventArgs参数得到矩形范围内绘制聚焦框
eGraphicsDrawRectangle ( New Pen ( New SolidBrush ( ColorBlack ) ) rfBound )
对菜单项的矩形区域绘制矩形框
End Sub
操作完成后保存修改此时再单击快捷键F运行程序可得到如图所示的界面
图【Visual Basic Net编程之DIY自己画菜单】运行界面之二
可见绘制的文件菜单项并没有完全显示出来并且后面的菜单项也没有显示这是因为菜单项的显示区域并没有设定而缺省的空间又不能完全显示造成的设定菜单项的显示区域大小是通过MeasureItem事件来完成的具体操作是在MenuItem的DrawItem事件后添加下列代码下列代码是是定义MenuItem的MeasureItem事件在此事件中设定菜单项的宽度(当然也可以设定高度等)
Private Sub MenuItem_MeasureItem ( ByVal sender As Object ByVal e As SystemWindowsFormsMeasureItemEventArgs ) Handles MenuItemMeasureItem
eItemWidth =
设定菜单项的宽度
End Sub
保存上述修改后单击快捷键F运行程序可得到图所示界面
图【Visual Basic Net编程之DIY自己画菜单】运行界面之三
可见文件菜单项就算绘制出来了由于其他菜单项没有绘制处理所以也未显示其他菜单项的绘制方法和文件菜单项的绘制方法基本相似以下是在上述完成的基础上对其他菜单项进行绘制从而得到图所示菜单的具体实现步骤
图【Visual Basic Net编程之DIY自己画菜单】运行界面之四
在FormVB中的MenuItem的MeasureItem事件处理程序之后添加下列代码下列代码是定义MenuItem的DrawItem事件其功能是对新建菜单项重新绘制
Private Sub MenuItem_DrawItem ( ByVal sender As Object ByVal e As SystemWindowsFormsDrawItemEventArgs ) Handles MenuItemDrawItem
Dim rfBound As RectangleF = New RectangleF ( eBoundsX eBoundsY eBoundsWidth eBoundsHeight )
根据DrawItemEventArgs参数获得菜单项矩形区域并存储到RectangleF类型实例中
Dim rfBound As Rectangle = New Rectangle ( eBoundsX eBoundsY eBoundsWidth eBoundsHeight )
根据DrawItemEventArgs参数获得菜单项矩形区域并存储到Rectangle类型实例中
Rectangle类型实例和RectangleF类型实例差不多但在后面代码中绘制菜单的函数是有区别的
eGraphicsFillRectangle ( New SolidBrush ( ColorLightGray ) rfBound )
Dim s As MenuItem = CType ( sender MenuItem )
Dim s As String = sText
获得菜单项对应的文本名称
Dim sfTemp As StringFormat = New StringFormat ( )
sfTempAlignment = StringAlignmentCenter
设定文本在矩形区域的对齐方式
sfTempLineAlignment = StringAlignmentCenter
Dim rcText As RectangleF = rfBound
rcTextWidth =
eGraphicsDrawString ( s New Font ( 宋体 ) New SolidBrush ( ColorBlue ) rcText sfTemp )
eGraphicsDrawRectangle ( New Pen ( New SolidBrush ( ColorLightGray ) ) rfBound )
If eState = ( DrawItemStateNoAccelerator Or DrawItemStateSelected ) Then
eGraphicsFillRectangle ( New SolidBrush ( ColorLightYellow ) rfBound )
eGraphicsDrawString ( s New Font ( 宋体 FontStyleBold Or FontStyleUnderline ) New SolidBrush ( ColorRed ) rcText sfTemp )
eGraphicsDrawRectangle ( New Pen ( New SolidBrush ( ColorBlack ) ) rfBound )
eDrawFocusRectangle ( )
End If
End Sub
MenuItem的DrawItem事件处理代码之后添加下列代码下列代码是定义MenuItem的MeasureItem事件在此事件中实现设定新建菜单项的长度和高度
Private Sub MenuItem_MeasureItem ( ByVal sender As Object ByVal e As SystemWindowsFormsMeasureItemEventArgs ) Handles MenuItemMeasureItem
eItemWidth =
设定菜单项的宽度
eItemHeight =
设定菜单项的高度
End Sub
在完成上述操作步骤后再在MenuItem的MeasureItem事件处理程序之后添加下列代码下列代码是定义MenuItem的DrawItem事件其功能是对打开菜单项重新绘制
Private Sub MenuItem_DrawItem ( ByVal sender As Object ByVal e As SystemWindowsFormsDrawItemEventArgs ) Handles MenuItemDrawItem
Dim rfBound As RectangleF = New RectangleF ( eBoundsX eBoundsY eBoundsWidth eBoundsHeight )
根据DrawItemEventArgs参数获得菜单项矩形区域并存储到RectangleF类型实例中
Dim rfBound As Rectangle = New Rectangle ( eBoundsX eBoundsY eBoundsWidth eBoundsHeight )
根据DrawItemEventArgs参数获得菜单项矩形区域并存储到Rectangle类型实例中
Rectangle类型实例和RectangleF类型实例差不多但在后面代码中绘制菜单的函数是有区别的
Dim s As MenuItem = CType ( sender MenuItem )
Dim s As String = sText
Dim sfTemp As StringFormat = New StringFormat ( )
sfTempAlignment = StringAlignmentCenter
sfTempLineAlignment = StringAlignmentCenter
Dim rcText As RectangleF = rfBound
rcTextWidth =
eGraphicsDrawString ( s New Font ( Veranda ) New SolidBrush ( ColorBlue ) rcText sfTemp )
eGraphicsDrawRectangle ( New Pen ( New SolidBrush ( ColorLightGray ) ) rfBound )
If eState = ( DrawItemStateNoAccelerator Or DrawItemStateSelected ) Then
eGraphicsFillRectangle ( New SolidBrush ( ColorLightYellow ) rfBound )
eGraphicsDrawString ( s New Font ( Veranda FontStyleBold Or FontStyleUnderline ) New SolidBrush ( ColorRed ) rcText sfTemp )
eGraphicsDrawRectangle ( New Pen ( New SolidBrush ( ColorBlack ) ) rfBound )
eDrawFocusRectangle ( )
End If
End Sub
MenuItem的DrawItem事件处理代码之后添加下列代码下列代码是定义MenuItem的MeasureItem事件在此事件中实现设定新建菜单项的长度和高度
Private Sub MenuItem_MeasureItem ( ByVal sender As Object ByVal e As SystemWindowsFormsMeasureItemEventArgs ) Handles MenuItemMeasureItem
eItemWidth =
设定菜单项的宽度
eItemHeight =
设定菜单项的高度
End Sub
在上述步骤都正确完成后本文介绍的手工绘制菜单就完成此时单击快捷键F运行
程序就可以得到图所示的运行界面
四.总结
Visual 中实现绘制菜单最重要的是掌握DrawItem事件和MeasureItem事件用法及其绘制菜单时所要使用到的各种图形图象方法如绘制名称色彩填充等当然在绘制菜单时首先把菜单项的OwnerDraw属性设定为True因为这是触发DrawItem事件和MeasureItem事件的前提本文实现的菜单虽不美观但本文介绍的方法却是很实用的在上述项目的基础上进行一定的修改如再调用其他的绘制方法一定可以完成一个更美观的菜单来