在Windows应用程序中,利用弹出式菜单(Pop-up Menu)是增加软件易用性的一个重要方式。本文将向大家介绍在VB6.0中实现弹出式菜单的几种方法。
利用VB6.0内置的PopupMenu方法
PopupMenu方法(Method)是VB6.0内置的实现弹出式菜单的方法,用于在MDIForm或Form等对象中的鼠标点位置或指定位置显示弹出式菜单。其语法为:
Object.PopupMenu menuname, flags, x, y, boldcommand
说明如下:
Object | 可选项,可以是PropertyPage, Usercontrol, UserDocument, Form, MDIForm等对象之一,如果该部分省略,则具有焦点(Focus)的Form对象将作为此Object。 | ||
Menuname | 必须,将被显示的弹出式菜单的名称,此菜单必须至少包含一个子菜单 | ||
Flags | 可选项,一个值或常数,设置弹出式菜单显示的位置及行为方式,定义如下: | ||
常数(位置) | 值 | 说明 | |
VbPopupMenuLeftAlign | 0 | (缺省值)弹出式菜单左对齐于X | |
VbPopupMenuCenterAlign | 4 | 菜单居中于X | |
VbPopupMenuRightAlign | 8 | 弹出式菜单右对齐于X | |
常数(行为) | 值 | 说明 | |
VbPopupMenuLeftButton | 0 | (缺省值)只能通过点击鼠标左键来选择弹出式菜单的菜单项 | |
VbPopupMenuRightButton | 2 | 可以通过点击鼠标的左键或右键来选择弹出式菜单的菜单项 | |
X | 可选项,设定显示弹出式菜单的X坐标,如省略,鼠标点坐标将被作为X使用 | ||
Y | 可选项,设定显示弹出式菜单的Y坐标,如省略,鼠标点坐标将被作为Y使用 | ||
Boldcommand | 可选项,定义弹出式菜单中某一个菜单项的名称,该菜单项文字将被加粗显示,如省略该项,则无菜单项文字被加粗。 |
通过设置对象(Object)的Scalemode属性来规定X,Y坐标的度量单位,X,Y坐标设定弹出式菜单在对象(Object)中显示的相对位置,如果省略X,Y,则弹出式菜单将显示在当前鼠标点位置。
当用PopupMenu方法激活弹出菜单后,要等到用户选择了弹出菜单中的某个菜单项之后(这种情况下,还要先运行被选择菜单项的相应代码)或在表单其它位置单击鼠标左键消除弹出菜单后,后面的代码才能继续执行。并且,一次只能激活一个弹出式菜单,当已经有一个弹处菜单被激活或已经有一个下拉菜单被打开时,对PopupMenu方法的调用将被忽略。
下面的例子演示当用户在表单上点击鼠标右键时,在鼠标点处显示弹出式菜单。欲试验此例子,建立一个表单,在表单中建立一个菜单控件,将其命名为mnuFile(mnuFile菜单至少包含一个子菜单)。在表单的声明(Declaration)区域加入如下代码:
Private Sub Form_MouseDown (Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = vbRightButton Then
PopupMenu mnuFile
End If
End Sub
PopupMenu方法是VB6.0内置的方法,使用起来方便简单,但该方法有一个不足,即当点击鼠标弹出菜单后,如果不选择菜单项而在其他位置点击鼠标,则菜单并不会在新的鼠标点处显示。这虽然不至于影响应用程序的功能,但却降低了易用性。
利用Windows API函数
除了利用VB6.0内置的PopupMenu方法来实现弹出式菜单外,还可以利用Windows 的应用程序接口(API)函数中的菜单函数来实现弹出式菜单。
利用API的菜单函数实现弹出式菜单与VB6.0内置的PopupMenu方法相比,要复杂一些,但却弥补了PopupMenu方法的不足点,即当弹出菜单后不选择菜单项而在其它位置点击鼠标时,弹出式菜单会立即出现在那个位置。并且利用API函数,编程者可以更加灵活、自由度更大地实现弹出式菜单。
本文用到的API函数为:GetMenu, GetSubMenu, GetMenuItemInfo, InsertMenuItem, CreatePopupMenu, DestroyMenu, TrackPopupMenu。下面先简单介绍一下这几个函数。
GetMenu | GetMenu函数返回指定窗口的菜单的句柄 | ||||
语法:GetMenu ( HWnd ) | |||||
参数的意义 | |||||
HWnd | 窗口句柄,该窗口所包含的菜单的句柄将被函数返回 | ||||
GetSubMenu | GetSubMenu函数返回下拉菜单或被指定菜单项激活的子菜单的句柄 | ||||
语法:GetSubMenu ( hMenu, nPos ) | |||||
参数的意义 | |||||
Hmenu | 菜单句柄 | ||||
NPos | 定义激活下拉菜单或子菜单的菜单项在所给菜单中的相对位置(起始为0) | ||||
GetMenuItemInfo | GetMenuItemInfo函数返回菜单项的信息 | ||||
语法:GetMenuItemInfo ( hMenu, uItem, fByPosition, lpmii ) | |||||
参数的意义 | |||||
Hmenu | 包含相应菜单项的菜单的句柄 | ||||
Uitem | 欲获得其信息的菜单项的标识号或位置,该参数的具体意义由fByPositon参数的值来决定 | ||||
FbyPosition | 用来定义uItem参数的意义,如果此参数的值为False,则uItem参数为菜单项的标识号,否则,为菜单项的位置 | ||||
Lpmii | 指向MENUITEMINFO结构变量的指针,该变量指定了需要返回菜单项的哪些信息,并接收这些信息。MENUITEMINFO结构各元素说明如下: | ||||
CbSize | 结构占用的字节数 | ||||
Fmask | 设置欲获得结构中哪些元素的值 | ||||
Ftype | 菜单项类型 | ||||
Fstate | 菜单项状态 | ||||
WID | 标识菜单项的16位值 | ||||
HsubMenu | 与菜单项关联的下拉菜单或子菜单的句柄 | ||||
HbmpChecked | 菜单项被选中时,显示在菜单项旁边的位图的句柄,该值为Null时使用缺省位图 | ||||
HbmpUnchecked | 菜单项未被选中时,显示在菜单项旁边的位图的句柄,该值为Null则不使用位图 | ||||
DwTypeData | 菜单项文字,长度在元素cch中给出 | ||||
Cch | 菜单项文字长度 | ||||
InsertMenuItem | InsertMenuItem函数在一菜单的指定位置插入一个新菜单项 | ||||
语法:InsertMenuItem ( hMenu, uItem, fByPosition, lpmii ) | |||||
参数的意义 | |||||
Hmenu | 新菜单项将被插入的菜单的句柄 | ||||
Uitem | 新菜单项将被插入在其之前的菜单项的标识号或位置,该参数的具体意义由fByPositon参数的值来决定 | ||||
FbyPosition | 用来定义uItem参数的意义,如果此参数的值为False,则uItem参数为菜单项的标识号,否则,为菜单项的位置 | ||||
Lpmii | 指向MENUITEMINFO结构变量的指针,该变量包含了新菜单项的信息 | ||||
CreatePopupMenu | CreatePopupMenu函数生成一个下拉菜单、子菜单或弹出式操单,菜单在初始时是空的,可以使用InsertMenuItem函数来插入菜单项 | ||||
语法:CreatePopupMenu ( ) | |||||
DestroyMenu | DestroyMenu函数清除指定的菜单并释放该菜单所占用的内存空间 | ||||
语法:DestroyMenu ( hMenu ) | |||||
参数的意义 | |||||
HMenu | 将被清除的菜单的句秉 | ||||
TrackPopupMenu | TrackPopupMenu函数在指定位置显示一个弹出式菜单,并跟踪菜单中菜单项的选择,弹出菜单可以出现在屏幕的任何位置 | ||||
语法:TrackPopupMenu (hMenu, uFlags, x, y, nReserved, hWnd, *PrcRect) | |||||
参数的意义 | |||||
HMenu | 被显示的弹出式菜单的句柄,此句柄可通过调用CreatePopupMenu函数生成一个新弹出式菜单获得,或调用GetSubMenu函数获得一个现有某子菜单的句柄 | ||||
UFlags | 一组标识符来指定函数的选项,意义如下 | ||||
常数 | 值 | 说明 | |||
TPM_CENTERALIGN | 4 | 设置该值,弹出式菜单水平居中于X | |||
TPM_LEFTALIGN | 0 | 设置该值,弹出式菜单左对齐于X | |||
TPM_RIGHTALIGN | 8 | 设置该值,弹出式菜单右对齐于X | |||
TPM_LEFTBUTTON | 0 | 设置该值,用户只能通过鼠标左键选择菜单项 | |||
TPM_RIGHTBUTTON | 2 | 设置该值,用户既可以通过鼠标左键也可以通过鼠标右键选择菜单项 | |||
X | 定义弹出菜单的水平位置(屏幕坐标系) | ||||
Y | 定义弹出菜单的垂直位置(屏幕坐标系) | ||||
Nreserved | 保留,必须为0 | ||||
HWnd | 拥有弹出式菜单的窗口的句柄,该窗口接收所有从该菜单传来的消息,该窗口在函数返回之前不从菜单接收WM_COMMAND消息 | ||||
PrcRect | 忽略 |
三.利用工程(Project)中其他表单的菜单作为当前表单的弹出菜单
如果表单(Form)的菜单中不包含弹出菜单需要的菜单项,那么可以新建一个表单,在新表单中建立一个与所需弹出菜单完全一样的菜单及相应代码。然后在MouseDown事件中利用GetMenu和GetSubMenu函数来获得新表单中的菜单句柄,再利用TrackPopupMenu函数激活弹出式菜单。
下面的例子演示当在表单中单击鼠标右键时,在鼠标点位置显示弹出式菜单,此弹出式菜单是通过调用另外一个表单中的菜单得到的。要试验这个例子,需要创建两个表单,一个命名为Form1,另一个命名为MnuForm。在MnuForm中加入一个菜单控件,将其命名为MnuFile(MnuFile中至少要包含一个子菜单)。添加一个模块(Module),在模块的声明(Declaration)区域添加如下代码:
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Public Declare Function GetMenu Lib "user32" (ByVal hwnd As Long) As Long
Public Declare Function GetSubMenu Lib "user32" (ByVal hMenu As Long, ByVal nPos As Long) As Long
Public Declare Function TrackPopupMenu Lib "user32" (ByVal hMenu As Long, ByVal wFlags As Long, ByVal x As Long, ByVal y As Long, ByVal nReserved As Long, ByVal hwnd As Long, lprc As RECT) As Long
在Form1的声明(Declaration)区域添加如下代码:
Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim IX As Integer, IY As Integer
Dim hMenu As Long, hSubMenu As Long, R As Integer
Dim menRect As RECT
If Button = vbRightButton Then
ScaleMode = TWIPS
IX = (X + Left) \ Screen.TwipsPerPixelX
IY = (Y + Top) \ Screen.TwipsPerPixelY
hMenu = GetMenu(MnuForm.hwnd) '获得MnuForm中的菜单句柄保存于hMenu
hSubMenu = GetSubMenu(hMenu, 0) '获得hMenu中的第一个子菜单的句柄保存于hSubMenu
R = TrackPopupMenu(hSubMenu, 2, IX, IY, 0, MnuForm.hwnd, menRect) '激活弹出菜单
End If
End Sub
利用表单中的菜单项实现弹出式菜单
如果表单的菜单中包含了弹出菜单所需的菜单项,那么可以通过CreatePopupMenu函数生成一个空的pop-up menu,然后利用GetMenuItemInfo函数从表单的菜单中获得相应菜单项的内容,再用InsertMenuItem函数将菜单项加入到pop-up menu中,最后使用TrackPopupMenu函数激活弹出式菜单。
下面的例子演示当在表单中单击鼠标右键时,在鼠标点位置显示弹出式菜单,此弹出式菜单是通过调用表单中的若干菜单项得到的。要试验这个例子,需要创建一个表单。在表单中加入一个菜单控件,将其命名为MnuFile,在MnuFile中至少要包含一个子菜单,将其命名为MnuOpen,MnuOpen的Caption值为“&Open”。添加一个模块(Module),在模块的Declaration区域添加如下代码:
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Public Type MENUITEMINFO
cbSize As Long
fMask As Long
fType As Long
fState As Long
wID As Long
hSubMenu As Long
hbmpChecked As Long
hbmpUnchecked As Long
dwItemData As Long
dwTypeData As String
cch As Long
End Type
Public Declare Function GetMenu Lib "user32" (ByVal hwnd As Long) As Long
Public Declare Function GetSubMenu Lib "user32" (ByVal hMenu As Long, ByVal nPos As Long) As Long
Public Declare Function TrackPopupMenu Lib "user32" (ByVal hMenu As Long, ByVal wFlags As Long, ByVal x As Long, ByVal y As Long, ByVal nReserved As Long, ByVal hwnd As Long, lprc As RECT) As Long
Public Declare Function CreatePopupMenu Lib "user32" () As Long
Public Declare Function DestroyMenu Lib "user32" (ByVal hMenu As Long) As Long
Public Declare Function GetMenuItemInfo Lib "user32" Alias "GetMenuItemInfoA" (ByVal hMenu As Long, ByVal un As Long, ByVal b As Long, lpMenuItemInfo As MENUITEMINFO) As Long
Public Declare Function InsertMenuItem Lib "user32" Alias "InsertMenuItemA" (ByVal hMenu As Long, ByVal un As Long, ByVal bool As Boolean, ByRef lpcMenuItemInfo As MENUITEMINFO) As Long
在表单的声明(Declaration)区域添加如下代码:
Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim IX As Integer, IY As Integer
Dim hMenu As Long, hSubMenu As Long, PMenu As Long
Dim theR As Long
Dim menRect As RECT
Dim MnuItmInfo As MENUITEMINFO, TempMnuItmInfo As MENUITEMINFO
Dim Dummy As Variant
If Button And vbRightButton Then
ScaleMode = vbTwips
IX = (X + Left) \ Screen.TwipsPerPixelX
IY = (Y + Top) \ Screen.TwipsPerPixelY
PMenu = CreatePopupMenu() '生成一个空弹出菜单
hMenu = GetMenu(Form1.hwnd) '获得Form1的菜单句柄保存于hMenu
hSubMenu = GetSubMenu(hMenu, 0) '获得hMenu的第一个子菜单的句柄保存于hSubMenu
With TempMnuItmInfo
.cbSize = Len(TempMnuItmInfo)
.dwTypeData = Space$(10)
.fMask = 126 '获得所有元素的值
.cch = 10
End With
MnuItmInfo = TempMnuItmInfo
Dummy = GetMenuItemInfo(hSubMenu, 0, True, MnuItmInfo) '获得hSubMenu第一个菜单
Dummy = InsertMenuItem(PMenu, 0, True, MnuItmInfo) '项的信息,将其插入到PMenu
.
.
.
MnuItmInfo = TempMnuItmInfo
Dummy = GetMenuItemInfo(hSubMenu, n, True, MnuItmInfo) '获得hSubMenu第n-1个菜
Dummy = InsertMenuItem(PMenu, n, True, MnuItmInfo) '单项的信息,将其插入到PMenu
theR = TrackPopupMenu(PMenu, 2, IX, IY, 0, Form1.hwnd, menRect) '激活弹出菜单
Dummy = DestroyMenu(PMenu)
End If
End Sub
相关文章参考:
※vb在 ListBox 之中点击右键弹出菜单
★VB部分相关文章推荐:★
※【引用】URLDownloadToFile_VB下载文件!
※【引用】使用CommonDialog的ShowSave后如何判断是保存还是※取消?
※vb 关于commondialog的多选VB获取Windows操作系统所有版本
※比CopyMemory还要快的函数SuperCopyMemory
更多精彩>>>