搜索了一下以前的论坛内容,虽然有几个问的,但最终好象都没有结果。
用.menu=false也不行,还是有一个菜单会出来。
有一个程序太平洋的例子http://www.dapha.net/down/list.asp?id=1704,这个文件也不在了。
上GOOGOO上找了半天,也没有答案。请帮忙解决。给100分。注意是完全屏蔽。
用.menu=false也不行,还是有一个菜单会出来。
有一个程序太平洋的例子http://www.dapha.net/down/list.asp?id=1704,这个文件也不在了。
上GOOGOO上找了半天,也没有答案。请帮忙解决。给100分。注意是完全屏蔽。
模块modMain的内容:
Option ExplicitPublic Const WM_RBUTTONDOWN = &H204
Public Const GWL_WNDPROC = (-4)Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal lhWnd As Long, ByVal lpClassName As String, ByVal lMax As Long) As LongPublic prevProc As Long
Public flaHwnd As LongPublic Sub Hook(ByVal hwnd As Long) prevProc = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WndProc)End SubPublic Sub UnHook(ByVal hwnd As Long) If prevProc <> GetWindowLong(hwnd, GWL_WNDPROC) Then
Call SetWindowLong(hwnd, GWL_WNDPROC, prevProc)
End IfEnd SubFunction WndProc(ByVal hwnd As Long, ByVal uMsg As Long, _
ByVal wp As Long, ByVal lp As Long) As Long Select Case uMsg
Case WM_RBUTTONDOWN
frmMain.PopupMenu frmMain.mnuPOP, 2
Case Else
WndProc = CallWindowProc(prevProc, hwnd, uMsg, wp, lp)
Exit Function
End Select WndProc = TrueEnd FunctionPublic Function EnumChildProc(ByVal hwnd As Long, _
ByVal lParam As Long) As Long '这个回调函数通过过滤所有的子窗口的类名,来判断是不是 Flash 控件,
'如果 Form 里的控件(子窗口)太多的话一定会影响启动速度的。我发现
'这个函数是从 TabIndex 最大的控件开始过滤的,也就是说,如果在设计
'窗体界面的时候最后才放置 Flash 控件的话,你就会第一个找到它的句柄
'了。而且 Flash 控件的类名会随着它的版本的不同而不同,所以我就用了
'一个 Like 语句。 'If GetClsName(hwnd) = "ATL:100536D0" Then
'If GetClsName(hwnd) = "ATL:582236D0" Then
If GetClsName(hwnd) Like "ATL:????????" Then
flaHwnd = hwnd
Hook flaHwnd
EnumChildProc = 0
Else
EnumChildProc = 1
End IfEnd FunctionPublic Function GetClsName(ByVal hwnd As Long) As String Dim xLen As Long
Dim sBuffer As String sBuffer = String(255, 0)
xLen = GetClassName(hwnd, sBuffer, 255) If xLen = 0 Then
GetClsName = ""
Else
GetClsName = Left(sBuffer, xLen)
End IfEnd Function
Option Explicit
'-------------OpenDialog 类的说明-------------------
'
'它的属性有
' 1.InitDir 缺省目录
' 2.DialogTitle 对话框标题
' 3.Filter 文件过滤器
' 4.Flags 对话框标志
' 5.Filename 缺省文件名
' 6.DefaultExt 缺省扩展名
' 7.Mode 打开/保存标志,True 表示打开对话框, False 表示保存对话框
'
'它的方法有
' 1.Execute 调用显示打开对话框
'---------------------------------------------------'-------------OpenDialog 类的调用-------------------
'
'在窗体的通用声明代码段里声明 OpenDialog 类
'例如:
' Dim cOpenDialog As OpenDialog'在窗体 Load 事件中定义一个新的 OpenDialog 类
'例如:
' Private Sub Form_Load()
' Set cOpenDialog = New OpenDialog
' End Sub'在窗体 Unload 事件中清除 OpenDialog 类
'例如:
' Private Sub Form_Unload(Cancel As Integer)
' Set cOpenDialog = Nothing
' End Sub'在需要打开对话框的地方设置它的属性并显示打开对话框
'例如:
' With cOpenDialog
' .InitDir = App.Path
' .DialogTitle = "选择文件"
' .Filter = "可执行文件 (*.exe;*.lnk)|*.exe;*.lnk|所有文件 (*.*)|*.*"
' .Flags = OFN_HIDEREADONLY + OFN_FILEMUSTEXIST + OFN_PATHMUSTEXIST
' If cOpenDialog.Execute Then
' Shell cOpenDialog.Filename, vbNormalFocus
' End If
' End With
'---------------------------------------------------Public Enum OpenDialogFlag
'它指定文件名列表框允许多重选择。
OFN_ALLOWMULTISELECT = &H200
'当文件不存在时对话框要提示创建文件。
'该标志自动设置 OFN_PathMustExist 和 OFN_FileMustExist 标志。
OFN_CREATEPROMPT = &H2000
'它使用类似资源管理器的打开一个文件的对话框模板。
'适用于 Windows 95 和 Windows NT 4.0。
OFN_EXPLORER = &H80000
'它指示返回的文件扩展名与 DefaultExt 属性指定的扩展名不一致。
'如果 DefaultExt 属性是 Null,或者扩展相匹配,或者没有扩展时,
'此标志不设置。当关闭对话框时,可以检查这个标志的值。
OFN_EXTENSIONDIFFERENT = &H400
'它指定只能输入文件名文本框已经存在的文件名。
'如果该标志被设置,则当用户输入非法的文件名时,要显示一个警告。
'该标志自动设置 OFN_PathMustExist 标志。
OFN_FILEMUSTEXIST = &H1000
'隐藏只读复选框。
OFN_HIDEREADONLY = &H4
'使用长文件名。
OFN_LONGNAMES = &H200000
'强制对话框将对话框打开时的目录置成当前目录。
OFN_NOCHANGEDIR = &H8
'不要间接引用外壳链接(也称作快捷方式)。
'缺省时,选取外壳链接会引起它被外壳间接引用。
OFN_NODEREFERENCELINKS = &H100000
'无长文件名。
OFN_NOLONGNAMES = &H40000
'它指定返回的文件不能具有只读属性,也不能在写保护目录下面。
OFN_NOREADONLYRETURN = &H8000
'它指定公共对话框允许返回的文件名中含有非法字符。
OFN_NOVALIDATE = &H100
'使“另存为”对话框当选择的文件已经存在时应产生一个信息框,
'用户必须确认是否覆盖该文件。
OFN_OVERWRITEPROMPT = &H2
'它指定只能输入有效路径。如果设置该标志,输入非法路径时,
'应显示一个警告信息。
OFN_PATHMUSTEXIST = &H800
'建立对话框时,只读复选框初始化为选定。
'该标志也指示对话框关闭时只读复选框的状态。
OFN_READONLY = &H1
'它指定忽略共享冲突错误。
OFN_SHAREAWARE = &H4000
'使对话框显示帮助按钮。
OFN_SHOWHELP = &H10
End EnumPrivate Type OPENFILENAME
lStructSize As Long
hwnd As Long
hInstance As Long
lpstrFilter As String
lpstrCustomFilter As String
nMaxCustFilter As Long
nFilterIndex As Long
lpstrFile As String
nMaxFile As Long
lpstrFileTitle As String
nMaxFileTitle As Long
lpstrInitialDir As String
lpstrTitle As String
Flags As Long
nFileOffset As Integer
nFileExtension As Integer
lpstrDefExt As String
lCustData As Long
lpfnHook As Long
lpTemplateName As String
End TypePrivate Declare Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameA" (pOpenfilename As OPENFILENAME) As Long
Private Declare Function GetSaveFileName Lib "comdlg32.dll" Alias "GetSaveFileNameA" (pOpenfilename As OPENFILENAME) As LongPrivate mvarFilter As String
Private mvarDialogTitle As String
Private mvarFilename As String
Private mvarInitDir As String
Private mvarDefaultExt As String
Private mvarFlag As OpenDialogFlag
Private mvarMode As Boolean
Private OFN As OPENFILENAMEPublic Property Let Mode(ByVal vData As Boolean) mvarMode = vDataEnd PropertyPublic Property Get Mode() As Boolean Mode = mvarModeEnd PropertyPublic Property Let Flags(ByVal vData As OpenDialogFlag) mvarFlag = vDataEnd PropertyPublic Property Get Flags() As OpenDialogFlag Flags = mvarFlagEnd PropertyPublic Property Let DefaultExt(ByVal vData As String) If vData <> "" Then
If InStr(1, vData, ".") = 0 Or Left(vData, 1) <> "." Then vData = "." & vData
End If mvarDefaultExt = vDataEnd PropertyPublic Property Get DefaultExt() As String DefaultExt = mvarDefaultExtEnd PropertyPublic Property Let InitDir(ByVal vData As String) mvarInitDir = vDataEnd PropertyPublic Property Get InitDir() As String InitDir = mvarInitDirEnd PropertyPublic Property Let Filename(ByVal vData As String) mvarFilename = vDataEnd PropertyPublic Property Get Filename() As String Filename = mvarFilenameEnd PropertyPublic Property Let DialogTitle(ByVal vData As String) mvarDialogTitle = vDataEnd PropertyPublic Property Get DialogTitle() As String DialogTitle = mvarDialogTitleEnd PropertyPublic Function Execute() As Boolean Dim ret As Long With OFN
.lStructSize = Len(OFN)
.Flags = Flags
.lpstrDefExt = DefaultExt
.lpstrFilter = Filter
.lpstrInitialDir = InitDir
.lpstrTitle = DialogTitle
.nMaxFile = 255
.nMaxFileTitle = 255
.lpstrFile = Filename & String(250 - Len(Filename), 0)
.lpstrFileTitle = String(255, 0)
.nFilterIndex = 1
End With If Mode Then
ret = GetOpenFileName(OFN)
Else
ret = GetSaveFileName(OFN)
End If If ret <> 0 Then
If InStr(OFN.lpstrFile, vbNullChar) > 0 Then
Filename = Left(OFN.lpstrFile, InStr(OFN.lpstrFile, vbNullChar) - 1)
End If
Execute = True
Else
Execute = False
End IfEnd FunctionPublic Property Let Filter(ByVal vData As String) vData = Replace(vData, "|", vbNullChar)
mvarFilter = vDataEnd PropertyPublic Property Get Filter() As String
Filter = mvarFilter
End PropertyFunction Replace(Source As String, SrcText As String, DesText As String) As String Dim Txt As String, Word1 As String, Word2 As String
Dim n As Integer Txt = Source n = InStr(Txt, SrcText)
While n <> 0
Word1 = Left(Txt, n - 1)
Word2 = Mid(Txt, n + Len(SrcText))
Txt = Word1 + DesText + Word2
n = InStr(n + 1, Txt, SrcText)
Wend Replace = TxtEnd FunctionPrivate Sub Class_Initialize()
mvarMode = True
End Sub
Option ExplicitPrivate Sub Form_Load() Dim ret As Long Me.Caption = Me.Caption & " - [" & App.Major & "." & App.Minor & "." & App.Revision & "]"
ret = EnumChildWindows(Me.hwnd, AddressOf EnumChildProc, ByVal 0&)End SubPrivate Sub Form_Resize() Flash.Move 0, 0, Me.ScaleWidth, Me.ScaleHeightEnd SubPrivate Sub Form_Unload(Cancel As Integer) UnHook flaHwndEnd SubPrivate Sub mnuPOPClose_Click() Flash.Movie = ""End SubPrivate Sub mnuPOPOpen_Click() Dim OpenDialog As COpenDialog Set OpenDialog = New COpenDialog With OpenDialog
.DefaultExt = ".swf"
.DialogTitle = "打开"
.Filter = "swf 文件 (*.swf)|*.swf"
.Flags = OFN_FILEMUSTEXIST + OFN_PATHMUSTEXIST + OFN_HIDEREADONLY
If .Execute Then
Flash.BGColor = 0
Flash.Movie = .Filename
Flash.ScaleMode = 2
Flash.Loop = False
End If
End With Set OpenDialog = NothingEnd Sub
关注hisofty(瘦马) 的做法.
如果不考虑可能的后果。
楼主不给我点分,说不过去呀
关于子类的安全性问题
这是VB6设计的缺陷
不允许主工程带子类的代码在调试环境下运行
解决方案:
1.编译成exe再运行
2.将SubClass功能分离到一个ActiveX DLL中
vbaccelerator.com的很不错:
http://vbaccelerator.com/home/VB/Code/Libraries/Subclassing/SSubTimer/VB6_SSubTmr_Source_Code.zip
Flash控件的右键菜单,似乎不是WM_CONTEXTMENU消息,我拦截了这个消息,不行 可以直接拦截wm_rbuttondown,wm_rbuttonup
' 窗体模块
Option Explicit
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Sub Form_Load()
Dim Handle As Long ' 窗口句柄
Dim ParentHandle As Long ' 父窗口句柄
ParentHandle = FindWindow("ThunderFormDC", "Form1") ' 获得父窗口句柄
Handle = FindWindowEx(ParentHandle, 0&, "MacromediaFlashPlayerActiveX", vbNullString) ' 获得窗口句柄
ret = SetWindowLong(Handle, GWL_WNDPROC, AddressOf WindowProc)
End Sub
' 标准模块
Option Explicit
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private 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, ByVal lprc As Any) As Long
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Declare Function GetMenu Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetSubMenu Lib "user32" (ByVal hMenu As Long, ByVal nPos As Long) As Long
Public Const GWL_WNDPROC = (-4)
Private Const TPM_LEFTALIGN = &H0&
Private Const WM_RBUTTONDOWN = &H204
Private Type POINTAPI
x As Long
y As Long
End Type
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Public ret As Long
' SetWindowLong 的回调函数, 利用 Msg 拦截消息
Function WindowProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If Msg = WM_RBUTTONDOWN Then
Dim pos As POINTAPI, hMenu As Long
GetCursorPos pos
hMenu = GetSubMenu(GetMenu(Form1.hwnd), 0)
TrackPopupMenu hMenu, TPM_LEFTALIGN, pos.x, pos.y, ByVal 0&, hwnd, ByVal 0&
Exit Function
End If
WindowProc = CallWindowProc(ret, hwnd, Msg, wParam, lParam)
End Function
上面的代码我在Windows XP+VB6下调试通过。
ParentHandle = FindWindow("ThunderFormDC", "Form1") ' 获得父窗口句柄
hMenu = GetSubMenu(GetMenu(Form1.hwnd), 0)
这两句中的form1改成我的工程的名字,别的就不用动了?
另外,“下面的代码得先用菜单编辑器在窗体上创建一个菜单。”能详细解释一下吗,创建一个什么样的菜单?我的工程里已经有一个菜单了,该怎么办?
我的API学的不好,请详细说明一下。
ParentHandle = FindWindow("ThunderFormDC", "Form1")
中的Form1应该是窗体的caption,也就是标题。至于菜单不建也行,那的话,会弹出自己建的菜单取代flash默认的菜单。
用下面的代码吧,我改了改。窗体模块:
Option Explicit
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Sub Form_Load()
Dim hFlash As Long
hFlash = FindWindowEx(Me.hwnd, 0&, "MacromediaFlashPlayerActiveX", vbNullString)
ret = SetWindowLong(hFlash, GWL_WNDPROC, AddressOf WindowProc)
End Sub标准模块:
Option Explicit
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Const GWL_WNDPROC = (-4)
Private Const WM_RBUTTONDOWN = &H204
Private Type POINTAPI
x As Long
y As Long
End Type
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Public ret As Long
' SetWindowLong 的回调函数, 利用 Msg 拦截消息
Function WindowProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If Msg = WM_RBUTTONDOWN Then Exit Function
WindowProc = CallWindowProc(ret, hwnd, Msg, wParam, lParam)
End Function
FindWindow中的"MacromediaFlashPlayerActiveX"参数指的是窗口的类名,你用spy++查一下看看你的窗体中的Flash控件的类名是不是这个?
如果不是得改一下。
Dim ret As Long
ret = EnumChildWindows(Me.hwnd, AddressOf EnumChildProc, ByVal 0&)
End SubPrivate Sub Form_Resize()
Flash.Move 0, 0, Me.ScaleWidth, Me.ScaleHeight
End SubPrivate Sub Form_Unload(Cancel As Integer)
UnHook flaHwnd
End Sub'modMain:Public Const WM_RBUTTONDOWN = &H204
Public Const GWL_WNDPROC = (-4)Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal lhWnd As Long, ByVal lpClassName As String, ByVal lMax As Long) As LongPublic prevProc As Long
Public flaHwnd As LongPublic Sub Hook(ByVal hwnd As Long) prevProc = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WndProc)End SubPublic Sub UnHook(ByVal hwnd As Long) If prevProc <> GetWindowLong(hwnd, GWL_WNDPROC) Then
Call SetWindowLong(hwnd, GWL_WNDPROC, prevProc)
End IfEnd SubFunction WndProc(ByVal hwnd As Long, ByVal uMsg As Long, _
ByVal wp As Long, ByVal lp As Long) As Long Select Case uMsg
Case WM_RBUTTONDOWN
frmMain.PopupMenu frmMain.mnuPOP, 2
Case Else
WndProc = CallWindowProc(prevProc, hwnd, uMsg, wp, lp)
Exit Function
End Select WndProc = TrueEnd FunctionPublic Function EnumChildProc(ByVal hwnd As Long, _
ByVal lParam As Long) As Long '这个回调函数通过过滤所有的子窗口的类名,来判断是不是 Flash 控件,
'如果 Form 里的控件(子窗口)太多的话一定会影响启动速度的。我发现
'这个函数是从 TabIndex 最大的控件开始过滤的,也就是说,如果在设计
'窗体界面的时候最后才放置 Flash 控件的话,你就会第一个找到它的句柄
'了。而且 Flash 控件的类名会随着它的版本的不同而不同,所以我就用了
'一个 Like 语句。 'If GetClsName(hwnd) = "ATL:100536D0" Then
'If GetClsName(hwnd) = "ATL:582236D0" Then
If GetClsName(hwnd) Like "ATL:????????" Then
flaHwnd = hwnd
Hook flaHwnd
EnumChildProc = 0
Else
EnumChildProc = 1
End IfEnd FunctionPublic Function GetClsName(ByVal hwnd As Long) As String Dim xLen As Long
Dim sBuffer As String sBuffer = String(255, 0)
xLen = GetClassName(hwnd, sBuffer, 255) If xLen = 0 Then
GetClsName = ""
Else
GetClsName = Left(sBuffer, xLen)
End IfEnd Function
http://www.maximsoft.net/download/屏蔽flash控件右击菜单.rar
下载完后,请讲一下。
我有一个屏蔽flash控件右击菜单的完整例子,下载地址为:
http://www.maximsoft.net/download/killflashmenu.rar
下载完后,请讲一下。
楼主能不能把你的程序的.frm文件和.bas文件用记事本打开,把代码贴过来。
真是怪事。 :(
hFlash = FindWindowEx(Me.hwnd, 0&, "MacromediaFlashPlayerActiveX", vbNullString)
改成
hFlash = FindWindowEx(picPart.hwnd, 0&, "MacromediaFlashPlayerActiveX", vbNullString)
就可以了。
FindWindowEx的第一个参数是要找的窗口的父窗口的句柄,而你的Flash控件的父窗口是一个PictureBox(picPart),而不是Form。
' 窗体模块
Option Explicit
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Sub Form_Load()
Dim Handle As Long ' 窗口句柄
Dim ParentHandle As Long ' 父窗口句柄
ParentHandle = FindWindow("ThunderFormDC", "Form1") ' 获得父窗口句柄
Handle = FindWindowEx(ParentHandle, 0&, "MacromediaFlashPlayerActiveX", vbNullString) ' 获得窗口句柄
ret = SetWindowLong(Handle, GWL_WNDPROC, AddressOf WindowProc)
End Sub
' 标准模块
Option Explicit
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private 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, ByVal lprc As Any) As Long
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Declare Function GetMenu Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetSubMenu Lib "user32" (ByVal hMenu As Long, ByVal nPos As Long) As Long
Public Const GWL_WNDPROC = (-4)
Private Const TPM_LEFTALIGN = &H0&
Private Const WM_RBUTTONDOWN = &H204
Private Type POINTAPI
x As Long
y As Long
End Type
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Public ret As Long
' SetWindowLong 的回调函数, 利用 Msg 拦截消息
Function WindowProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If Msg = WM_RBUTTONDOWN Then
Dim pos As POINTAPI, hMenu As Long
GetCursorPos pos
hMenu = GetSubMenu(GetMenu(Form1.hwnd), 0)
TrackPopupMenu hMenu, TPM_LEFTALIGN, pos.x, pos.y, ByVal 0&, hwnd, ByVal 0&
Exit Function
End If
WindowProc = CallWindowProc(ret, hwnd, Msg, wParam, lParam)
End Function
上面的代码我在Windows XP+VB6下调试通过。关键是标准模块中的这两句:
第一句获得窗口的菜单句柄,注意Form1.hwnd要改成实际有菜单的那个窗体。
第二句是在屏幕中指定的位置弹出一个菜单。
hMenu = GetSubMenu(GetMenu(Form1.hwnd), 0)
TrackPopupMenu hMenu, TPM_LEFTALIGN, pos.x, pos.y, ByVal 0&, hwnd, ByVal 0&
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)
Declare Function TrackPopupMenuBynum& Lib "user32" Alias "TrackPopupMenu" (ByVal hMenu As Long, ByVal wFlags As Long, ByVal x As Long, ByVal y As Long, ByVal nReserved As Long, ByVal hwnd As Long, ByVal lprc As Long)
说明
在屏幕的任意地方显示一个弹出式菜单
返回值
Long,非零表示成功,零表示失败。会设置GetLastError
参数表
参数 类型及说明
hMenu Long,弹出式菜单的句柄
wFlags Long,位置标志和鼠标追踪标志的组合,见下表
位置标志 说明
TPM_CENTERALIGN 菜单在指定位置水平居中
TPM_LEFTALIGN 菜单的左侧置于水平x坐标处
TPM_RIGHTALIGN 菜单的右侧置于水平x坐标处
TPM_LEFTBUTTON 鼠标左键标准运作方式
TPM_RIGHTBUTTON 用鼠标右键进行菜单追踪
x,y Long,这个点指定了弹出式菜单在屏幕坐标系统中的位置
nReserved Long,未使用,设为零
hwnd Long,用于接收弹出式菜单命令的窗口的句柄。应该使用窗体的窗口句柄——窗体中有一个菜单能象弹出式菜单那样接收相同的命令ID集
lprc Rect,用屏幕坐标定义的一个矩形,如用户在这个矩形的范围内单击,则弹出式菜单不会关闭。如单击弹出式菜单之外的任何一个地方,则会关闭菜单。可以设为NULL
注解
用这个函数创建的菜单,菜单中的命令ID并不与vb期望的那些相符
Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
说明
这是windows广泛采用的一种数据结构,通常作为参数传递给许多api函数。RECT结构表示一个矩形区域,left和top字段描叙了矩形第一个角(通常是左上角),right和bottom字段描叙了矩形的第二个角(通常是右下角)。这两个位置决定了矩形的大小与位置。这些字段采用的单位及坐标系统取决于当前的有效缩放比例、准备表示的对象以及准备调用的api函数。并不要求bottom字段的绝对值大于top字段,而且也可以为负数。
注意
由right及bottom字段指定的点通常不是矩形的一部分;矩形对象描叙的是个空矩形(其中不包含像素);RECT结构要求按引用传递给windows函数,不要试图使用ByVal
ShockWave Flash,一个在VB中嵌入Flash的控件。