在VB的菜單編輯器中,快捷鍵很少,如果想要實現Ctrl+Shift+O這樣的快捷鍵,都無法解決。後來利用API以及鉤子,實現了代碼,代碼如下

‘模塊代碼


Option Explicit

''

'' Copyright ?1997-1999 Brad Martinez, http://www.mvps.org

''

'' A general purpose subclassing module w/ debugging code

''

'' - Code was developed using, and is formatted for, 8pt. MS Sans Serif font

'' ==============================================


Public Declare Function GetProp Lib "user32" Alias "GetPropA" (ByVal hwnd As Long, ByVal lpString As Any) As Long

Public Declare Function SetProp Lib "user32" Alias "SetPropA" (ByVal hwnd As Long, ByVal lpString As String, ByVal hData As Long) As Long

Public Declare Function RemoveProp Lib "user32" Alias "RemovePropA" (ByVal hwnd As Long, ByVal lpString As String) As Long


Public Const WS_BORDER = &H800000

Public Const WS_CLIPCHILDREN = &H2000000


Public Enum GWL_nIndex

GWL_WNDPROC = (-4)

'' GWL_HWNDPARENT = (-8)

GWL_ID = (-12)

GWL_STYLE = (-16)

GWL_EXSTYLE = (-20)

'' GWL_USERDATA = (-21)

End Enum


Public Const WM_HOTKEY = &H312

Public Declare Function RegisterHotKey Lib "user32" (ByVal hwnd As Long, ByVal id As Long, ByVal fsModifIErs As Long, ByVal vk As Long) As Long

Public Declare Function UnregisterHotKey Lib "user32" (ByVal hwnd As Long, ByVal id As Long) As Long



Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As GWL_nIndex) As Long

Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As GWL_nIndex, ByVal dwNewLong As Long) As Long


Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Public Declare Function DefWindowProc Lib "user32" Alias "DefWindowProcA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long


Private Const LMEM_FIXED = &H0

Private Const LMEM_ZEROINIT = &H40

Private Const LPTR = (LMEM_FIXED Or LMEM_ZEROINIT)

Private Declare Function LocalAlloc Lib "kernel32" (ByVal uFlags As Long, ByVal uBytes As Long) As Long

Private Declare Function LocalFree Lib "kernel32" (ByVal hMem As Long) As Long

Private Declare Function lstrcpyA Lib "kernel32" (lpString1 As Any, lpString2 As Any) As Long


Private Const OLDWNDPROC = "OldWndProc"

Private Const OBJECTPTR = "ObjectPtr"


'' Allocated string pointer filled with OLDWNDPROC string and used with all

'' CallWindowProc(GetProp(hwnd, m_lpszOldWndProc), ...) calls.

Private m_lpszOldWndProc As Long


#If DEBUGWINDOWPROC Then

'' maintains a WindowProcHook reference for each subclassed window.

'' the window''s handle is the collection item''s key string.

Private m_colWPHooks As New Collection

#End If

''


'' On first window subclass, allocates a memory buffer and copIEs the

'' "OldWndProc" string to the buffer. On last unsubclass, frees and

'' zeros the allocated buffer. The pointer to the buffer is passed directly

'' to GetProp when retrIEing the subclassed window''s original window

'' procedure pointer, eliminating VB''s Unicode to ANSI string conversion

'' in our window procedures.


Private Sub SetWndProcPropertyBuffer(hwnd As Long, fAdd As Boolean)

Static colhWnds As New Collection

'' Collection holds the handles of all subclassed Windows,

'' ensuring an accurate count of unique handles.

On Error Resume Next

If fAdd Then

colhWnds.Add hwnd, CStr(hwnd)

Else

colhWnds.Remove CStr(hwnd)

End If

On Error GoTo 0

'' If adding a window handle and the buffer is not yet

'' allocated, allocate it.

If fAdd Then

If (m_lpszOldWndProc = 0) Then

m_lpszOldWndProc = LocalAlloc(LPTR, Len(OLDWNDPROC))

If m_lpszOldWndProc Then

Call lstrcpyA(ByVal m_lpszOldWndProc, ByVal OLDWNDPROC)

''Debug.Print "wndproc buffer allocated"

End If

End If

'' If removing a window handle, the collection count is zero, and the

'' buffer is allocated, deallocate the buffer memory and zero the variable

ElseIf (fAdd = False) And (colhWnds.Count = 0) Then

If m_lpszOldWndProc Then

Call LocalFree(m_lpszOldWndProc)

m_lpszOldWndProc = 0

''Debug.Print "wndproc buffer freed"

End If

End If '' fAdd


End Sub


Public Function SubClass(hwnd As Long, _

lpfnNew As Long, _

Optional objNotify As Object = Nothing) As Boolean

Dim lpfnOld As Long

Dim fSuccess As Boolean

On Error GoTo Out


If GetProp(hwnd, OLDWNDPROC) Then

SubClass = True

Exit Function

End If

Call SetWndProcPropertyBuffer(hwnd, True)

#If (DEBUGWINDOWPROC = 0) Then

lpfnOld = SetWindowLong(hwnd, GWL_WNDPROC, lpfnNew)


#Else

Dim objWPHook As WindowProcHook

Set objWPHook = CreateWindowProcHook

m_colWPHooks.Add objWPHook, CStr(hwnd)

With objWPHook

Call .SetMainProc(lpfnNew)

lpfnOld = SetWindowLong(hwnd, GWL_WNDPROC, .ProcAddress)

Call .SetDebugProc(lpfnOld)

End With


#End If

If lpfnOld Then

fSuccess = SetProp(hwnd, OLDWNDPROC, lpfnOld)

If (objNotify Is Nothing) = False Then

fSuccess = fSuccess And SetProp(hwnd,OBJECTPTR, ObjPtr(objNotify))

End If

End If

Out:

If fSuccess Then

SubClass = True

Else

If lpfnOld Then Call SetWindowLong(hwnd, GWL_WNDPROC, lpfnOld)

MsgBox "Error subclassing window &H" & Hex(hwnd) & vbCrLf & vbCrLf & _

"Err# " & Err.Number & ": " & Err.Description, vbExclamation

End If

End Function


Public Function UnSubClass(hwnd As Long) As Boolean

Dim lpfnOld As Long

lpfnOld = GetProp(hwnd, OLDWNDPROC)

If lpfnOld Then

If SetWindowLong(hwnd, GWL_WNDPROC, lpfnOld) Then

Call RemoveProp(hwnd, OLDWNDPROC)

Call RemoveProp(hwnd, OBJECTPTR)


#If DEBUGWINDOWPROC Then

'' remove the WindowProcHook reference from the collection

m_colWPHooks.Remove CStr(hwnd)

#End If

Call SetWndProcPropertyBuffer(hwnd, False)

UnSubClass = True

End If '' SetWindowLong

End If '' lpfnOld


End Function


Public Function WndProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long


Select Case uMsg

Case WM_HOTKEY

Select Case wParam

Case 100

Form1.ExecuteMenuCommand 100

Exit Function

End Select

End Select

WndProc = CallWindowProc(GetProp(hwnd, m_lpszOldWndProc), hwnd, uMsg, wParam, lParam)


End Function


''窗體代碼

Private Const MOD_ALT = &H1

Private Const MOD_CONTROL = &H2

Private Const MOD_SHIFT = &H4


Private Sub Form_Load()

Me.mnuFile_Open.Caption = "打開(&O)" & vbTab & "Ctrl+Shift+O"

RegisterHotKey Me.hwnd, 100, MOD_CONTROL + MOD_SHIFT, vbKeyO

SubClass Me.hwnd, AddressOf WndProc

End Sub


Private Sub Form_Unload(Cancel As Integer)

UnregisterHotKey Me.hwnd, 100

UnSubClass Me.hwnd

End Sub


Public Sub ExecuteMenuCommand(ByVal id As Long)

Select Case id

Case 100

mnuFile_Open_Click

End Select

End Sub


Private Sub mnuFile_Open_Click()

MsgBox mnuFile_Open.Caption

End Sub


Private Sub mnuFile_Save_Click()

MsgBox mnuFile_Save.Caption

End Sub
所顯示的菜單圖片:
![[圖片信息]](https://www.aspphp.online/bianchen/UploadFiles_4619/201701/2017011310543123.jpg)