|
创意无极限,用VB7制作您的个性化菜单 现代的软件开发,由于开发工具的大幅度进步,早已经让编程变得相当简单了,大家使用同样的工具,能不能写出好的程序来,在很大的程度上来说,已经不单单是技术的较量,而更多的是创意的竞争了。如何让用户对您的软件产生好感,我想除了过硬的技术以外,我们还需要一些新奇的东西,让用户有一种耳目一新的感觉!今天我就从软件界面中最常使用的菜单方面着手,教你制作一个个性化的菜单! VB7中的菜单,如果没有对它编写过特殊的处理程序,虽然不能说难看,但是和现在流行的Office,XP等程序的菜单相比,实在是不够漂亮,如果不想让您的软件看上去象是上个世纪的作品,那么就开始学习编写新的菜单吧! 在VB7中,有两种生成菜单的方法,一种是让系统自动生成,一种是让程序按照一定的指定方式生成。前者可以不用编程,就生成菜单,但是这并不是我们想要的;所以我们选择后者。 好,第一步,我们先在窗体上面放上一个MainMenu控件吧!至于菜单的标题,你喜欢怎么写就怎么写,为了做个示范,我的菜单如下: 文件 MenuItem1 新建 MenuItem2 打开 MenuItem3 保存 MenuItem4 退出 MenuItem5 运行一下这个窗体,我们发现在“文件”的菜单下面出现了四个关于文件的菜单项。好,第一步成功了!但这仅仅只是第一步!接下来,在进行下面的讲解前,我们假设在您的手头上面有一些图标文件,它们是C:\file.ico, C:\new.ico, C:\open.ico, C:\save.ico, C:\exit.ico ,当然如果你手上没有,也可以用其他的图标暂时代替一下,只要能有效果就可以了!好了,既然我们不要程序自动生成菜单,那么我们把这些菜单项的OwnerDraw属性修改一下,在菜单的属性框中找到OwnerDraw,并且设置成True。(这个时候再运行的话,由于还没有写菜单的生成方式,我们将看不到菜单!) 继续以前,我还要先简单说一下这个菜单的生成原理,菜单的生成靠的时两个过程,一个过程叫作:MeasureItems,另一个过程叫作DrawItem。前者的作用是对菜单的大小进行测量(Measure),后者是在测量的基础上进行绘制(Draw),我们要做的事情就是重新写这两个受保护的事件,让菜单按我们的意愿绘制出来(显示出来)。 添加一个模块,下面的添加这两个事件的具体代码,代码对初学者来说可能有些长,但是通读一遍绝对有很多好处!!我会尽量给出所有的注释。
Imports System Imports System.ComponentModel Imports System.Drawing Imports System.Drawing.Drawing2D Imports System.Drawing.Text Imports System.Windows.Forms ''''以上是这个模块要用到的一些名字空间(只是一些前缀!注意,写了这些,仅仅是为了简化下面的书写,并没有其他任何实际功能。)
Module IconsMenuMain Sub MeasureItems(ByVal EvMeasureItem As System.Windows.Forms.MeasureItemEventArgs , ByVal Mi As MenuItem, ByVal MyFont As Font) ''''开始“测量菜单”的事件 Dim sf As StringFormat = New StringFormat() ''''新建的字符格式对象 sf.HotkeyPrefix = HotkeyPrefix.Show ''''指定与文本相关的热键前缀的显示类型。将其设置为显示 sf.SetTabStops(60, New Single() {0}) ''''第一个参数firstTabOffset表示 ''''文本行开头和第一个制表位之间的空格数。 ''''第二个参数tabStops()表示 ''''制表位之间的距离(以空格数表示)的数组。 EvMeasureItem.ItemHeight = 22 ''''设置项目的高度,最好是字体的高度!! EvMeasureItem.ItemWidth=CInt(EvMeasureItem.Graphics.MeasureString (GetRealText(Mi), MyFont, 10000, sf).Width) + 10 ''''设置项目的宽度 sf.Dispose() sf = Nothing ''''销毁对象 End Sub
说明:上面这个事件决定了菜单的大小,也就是菜单的高度和宽度,如果您有兴趣的话,可以将高度常数22,宽度中的附加值常数10 都变成事件参数!这样就有不同高度的菜单了!下面这个事件,我就将窗体菜单的渐变色的起始色和最终色变成了参数,用来分别控制每个菜单中的文字渐变底色! Sub DrawItems(ByVal EvDrawItems As System.Windows.Forms.DrawItemEventArgs, ByVal Mi As MenuItem, ByVal m_Icon As Icon, ByVal StartColor As Color, ByVal EndColor As Color, ByVal MyFont As Font) Dim br As Brush ''''定义刷子 Dim fDisposeBrush As Boolean ''''是否销毁刷子的标志
If Not m_Icon Is Nothing Then ''''如果没有图标 If Not Mi.Checked Then ''''无论是否菜单项目被选择了,都先画图标,尽管后者什么都没有EvDrawItems.Graphics.DrawIcon(m_Icon, EvDrawItems.Bounds.Left + 2, EvDrawItems.Bounds.Top + 2) Else EvDrawItems.Graphics.DrawIcon(m_Icon, EvDrawItems.Bounds.Left + 2, EvDrawItems.Bounds.Top + 2)
Dim nPen As System.Drawing.Pen If Not Mi.Enabled Then nPen = New Pen(Color.DarkGray) ''''如果可用,就填充颜色DarkGray Else nPen = New Pen(Color.Gray) ''''不然用颜色Gray End If EvDrawItems.Graphics.DrawRectangle(nPen,1,EvDrawItems.Bounds.Top, 20, 20) EvDrawItems.Graphics.DrawRectangle(nPen, 3, EvDrawItems.Bounds.Top + 2, 16, 16) ''''画上两个框,两个框构成一个“回“字型 End If Else ''''如果有图标 If Mi.Checked Then ''''如果菜单处于复选状态 Dim nPen As System.Drawing.Pen 新建一个画笔对象 If Not Mi.Enabled Then 根据是否可用决定画笔颜色 nPen = New Pen(Color.DarkGray) Else nPen = New Pen(Color.Gray) End If EvDrawItems.Graphics.DrawRectangle(nPen, 1,EvDrawItems.Bounds.Top, 20, 20) ''''有图标,同时被选中,则只要画“回“字型中较大的一个框 Dim Pnts() As Point ReDim Pnts(2) ''''这三个点就是一个“勾“的位置 Pnts(0) = New Point(15, EvDrawItems.Bounds.Top + 6) Pnts(1) = New Point(8, EvDrawItems.Bounds.Top + 13) Pnts(2) = New Point(5, EvDrawItems.Bounds.Top + 10) ''''根据是否可用来决定画“勾“的颜色,并且画上“勾” 当然你可以根据需要来创造您自己菜单复选的图形 If Mi.Enabled Then EvDrawItems.Graphics.DrawLines(New Pen(Color.Black), Pnts) Else EvDrawItems.Graphics.DrawLines(New Pen(Color.Gray), Pnts) End If End If End If
Dim rcBk As Rectangle = EvDrawItems.Bounds rcBk.X += 24 ''''先获得一个和菜单一样大小的矩形,然后将矩形的X方向长度缩短,缩短的大小就是图标的大小,以后将以这个矩形作为菜单文字背景底色的填充范围
''''根据菜单项目是否被选中来决定是否使用颜色渐变刷子, ''''如果是则设置刷子的颜色,同时将是否销毁刷子的标志设置为真 If CBool(EvDrawItems.State And DrawItemState.Selected) Then br = New LinearGradientBrush(rcBk, StartColor, EndColor, 0) 设置起始色和最终色 fDisposeBrush = True ‘设置刷子销毁标志 Else br = SystemBrushes.Control ‘这个颜色是系统的默认 End If ''''画上渐变的菜单文字底色 EvDrawItems.Graphics.FillRectangle(br, rcBk)
If fDisposeBrush Then br.Dispose() ''''前面使用New方 [1] [2] 下一页 没有相关教程
|