明輝手游網(wǎng)中心:是一個免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺!

在系統(tǒng)菜單上添加自定義菜單項(xiàng)

[摘要]作者:馬鞍山鋼鐵總公司職工大學(xué) 王加龍 ---- 本文題目所說的系統(tǒng)菜單不是指應(yīng)用程序系統(tǒng)的菜單,而是指當(dāng)用戶用鼠標(biāo)左鍵單擊應(yīng)用程序窗體左上角的圖標(biāo)時彈出的菜單。同樣,當(dāng)用戶用鼠標(biāo)右鍵單擊應(yīng)用程序窗...
作者:馬鞍山鋼鐵總公司職工大學(xué) 王加龍

---- 本文題目所說的系統(tǒng)菜單不是指應(yīng)用程序系統(tǒng)的菜單,而是指當(dāng)用戶用鼠標(biāo)左鍵單擊應(yīng)用程序窗體左上角的圖標(biāo)時彈出的菜單。同樣,當(dāng)用戶用鼠標(biāo)右鍵單擊應(yīng)用程序窗體的標(biāo)題欄,或系統(tǒng)任務(wù)欄中的應(yīng)用程序標(biāo)題時,彈出的也是這個菜單。系統(tǒng)菜單與應(yīng)用程序菜單不一樣,系統(tǒng)菜單不受應(yīng)用程序控制,它是由Windows系統(tǒng)直接控制的。因此,在系統(tǒng)菜單上添加自定義菜單項(xiàng),就顯得比較困難。以下便是本人利用VB實(shí)現(xiàn)在系統(tǒng)菜單上添加自定義菜單項(xiàng)的方法。

---- 首先需要知道一點(diǎn)是系統(tǒng)菜單的工作過程。當(dāng)我們單擊系統(tǒng)菜單中某一項(xiàng)時,應(yīng)用程序窗口會收到一條WM_SYSCOMMAND消息,該消息包含了系統(tǒng)菜單中所單擊那一項(xiàng)的標(biāo)識符ID。此時,應(yīng)用程序窗口的默認(rèn)窗口函數(shù)會根據(jù)WM_SYSCOMMAND消息以及菜單標(biāo)識符ID執(zhí)行相應(yīng)的操作,完成菜單命令。如果我們能攔截到達(dá)窗口的WM_SYSCOMMAND消息,并且識別出菜單的標(biāo)識符ID,我們就能夠在系統(tǒng)菜單上添加自己的菜單項(xiàng),并且執(zhí)行指定的動作。下面的例子就是在系統(tǒng)菜單上添加一條分隔符和"關(guān)于…"菜單項(xiàng)。

---- 啟動Visual Basic,新建標(biāo)準(zhǔn)EXE工程,在工程中添加一標(biāo)準(zhǔn)模塊,名稱可以是默認(rèn)的。在標(biāo)準(zhǔn)模塊的聲明部分加入下列代碼:

'菜單API函數(shù)聲明
Public Declare Function GetSystemMenu Lib "user32"
(ByVal hwnd As Long, ByVal bRevert As Long) As Long
Public Declare Function AppendMenu Lib "user32" Alias
"AppendMenuA" (ByVal hMenu As Long, ByVal wFlags As Long,
ByVal wIDNewItem As Long, ByVal lpNewItem As Any) As Long
'菜單API函數(shù)常數(shù)聲明
Public Const MF_BYCOMMAND = &H0&
Public Const MF_SEPARATOR = &H800&
Public Const MF_STRING = &H0&
'有關(guān)窗口函數(shù)的API函數(shù)聲明
Public Declare Function SetWindowLong Lib
"user32" Alias "SetWindowLongA" (ByVal hwnd
As Long, ByVal nIndex As Long, ByVal
dwNewLong As Long) As Long
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 DefWindowProc Lib
"user32" Alias "DefWindowProcA" (ByVal
hwnd As Long, ByVal wMsg As Long,
ByVal wParam As Long, ByVal lParam As Long) As Long
'消息
Public Const GWL_WNDPROC = (-4)
Public Const WM_NCLBUTTONDOWN = &HA1
Public Const WM_NCRBUTTONDOWN = &HA4
Public Const WM_USER = &H400
Public Const WM_SYSCOMMAND = &H112
Public Const HTSYSMENU = 3
Public Const HTCAPTION = 2
'自定義菜單項(xiàng)的標(biāo)識號偏移量
Public Const IDM_SEPARATOR = 1
Public Const IDM_MYABOUT = 2
'其他變量
Dim sHwnd As Long
Dim OldProc As Long

接著可向標(biāo)準(zhǔn)模塊添加下面兩個過程:
Public Sub AddMenu(frm As Form)
'置換窗口函數(shù)過程

sHwnd = frm.hwnd
OldProc = SetWindowLong(frm.hwnd,
GWL_WNDPROC, AddressOf AddCallBack)

End Sub

Public Sub Release()
'釋放自定義窗口函數(shù)過程

SetWindowLong sHwnd, GWL_WNDPROC, OldProc

End Sub

最后向標(biāo)準(zhǔn)模塊中添加一自定義窗口函數(shù)過程:
Public Function AddCallBack(ByVal hwnd As Long,
ByVal wMsg As Long, ByVal wParam As Long,
ByVal lParam As Long) As Long
Select Case wMsg
Case WM_SYSCOMMAND '系統(tǒng)消息
Select Case wParam '測試
Case WM_USER + IDM_MYABOUT '
"關(guān)于..."菜單項(xiàng)
'此處可加入用戶需要自己處理
"關(guān)于…"菜單項(xiàng)的代碼
MsgBox "單擊了添加的菜單條目", vbOKOnly
Case Else '其它菜單項(xiàng)交換系統(tǒng)處理
AddCallBack = DefWindowProc(hwnd,
wMsg, wParam, lParam)
End Select
Exit Function
Case Else
AddCallBack = CallWindowProc(OldProc,
hwnd, wMsg, wParam, lParam)
End Select

End Function
關(guān)閉標(biāo)準(zhǔn)模塊的代碼窗口,
打開窗體的代碼窗口,
在Form_Load()過程中加入下列代碼:
'加載自定義窗口過程
AddMenu Me
'獲得系統(tǒng)菜單的句柄
Dim hMenu As Long
hMenu = GetSystemMenu(Me.hwnd, 0)
'在系統(tǒng)菜單中添加自定義2條菜單項(xiàng)
AppendMenu hMenu, MF_SEPARATOR
Or MF_BYCOMMAND,
IDM_SEPARATOR, vbNullString
'分隔符
AppendMenu hMenu, MF_BYCOMMAND
Or MF_STRING,
WM_USER + IDM_MYABOUT, "關(guān)于..."
'
"關(guān)于…"菜單項(xiàng)
在Form_Unload過程中加入下列代碼:
Release '釋放自定義窗口過程

---- 到此,代碼的輸入工作完成,接下來的是進(jìn)行測試。單擊啟動按鈕或按F5,啟動工程,用鼠標(biāo)單擊窗體左上角的圖標(biāo)彈出系統(tǒng)菜單,看看是否如愿。千萬要注意的一點(diǎn)是,在結(jié)束工程時,一定要用窗體右上角的關(guān)閉按鈕或者系統(tǒng)菜單中的關(guān)閉菜單項(xiàng),否則的話,會造成Visual Basic系統(tǒng)崩潰,出現(xiàn)非法操作的錯誤,所以在測試工程前,最好對工程進(jìn)行保存。
---- 以上程序在Windows95,Visual Basic6.0環(huán)境下調(diào)試通過。