A Visual Basic form's system menu normally displays a set of default commands for window-related commands, such as closing, minimizing, or maximizing the window. A program can add its own commands to this menu, as this tip explains. This is particularly useful because this menu can be displayed not only by clicking the icon at the left end of the title bar, but also by right-clicking the window's icon on the Windows task bar. This permits the user to send commands to the program while it remains minimized, a feature that can be useful in a variety of situations. As you might expect, you use Windows API functions to work with a form's system menu.
You start by getting a handle to the form's system menu using the GetSystemMenu API function. Once you have this handle you then use the AppendMenu API function to add the command to the end of the menu. Arguments to AppendMenu specify the menu item text and also assign a numeric ID that is used to identify when the command is selected by the user.
Once you have created the new menu command you must write the code that enables the program to respond to it. To do so, write a function with the proper arguments (as you'll see in the sample code). This function must be in a code module and not in a form. Code in this function will examine the data passed in the arguments to determine if your custom menu item was selected. If so, the function will take whatever actions are required. If not - that is, if one of the default system menu commands was selected - the command will be passed along for processing by the usual internal Windows mechanisms by calling the CallWindowProc API function.
The final step is to tell Windows to call your program's function when a system menu command is selected. This is accomplished by using the AddressOf operator to pass your function's address to the SetWindowLong API function.
You can try this out for yourself by creating a standard EXE project, adding a code module, and copying the code shown below into the code module. Then put the following line of code in the form's Load event procedure:
AddToSystemMenu Me.hWnd
The Windows API provides even more flexibility for customizing the system menu. You can, for example, add separator lines, enable and disable menu commands, insert a new command at any location in the menu and display checkmarks next to commands. These functions are beyond the scope of this tip, but you can find details in most Windows API reference books.
Private OriginalWindowProc As Long
Public Const MF_STRING = &H0&
Public Const MF_ENABLED = &H0&
Public Const IDM_MYMENUITEM = 2003
Public Const WM_SYSCOMMAND = &H112
Public Const GWL_WNDPROC = (-4)
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 String) 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 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 Sub AddToSystemMenu(ByVal hWnd As Long)
Dim hSystemMenu As Long
' Get the system menu's handle.
hSystemMenu = GetSystemMenu(hWnd, False)
' Append a custom command to the menu.
AppendMenu hSystemMenu, MF_STRING + MF_ENABLED, _
IDM_MYMENUITEM, "My Menu Item"
' Tell Windows to call MyMenuProc when a system
' menu command is selected.
OriginalWindowProc = SetWindowLong(hWnd, GWL_WNDPROC, _
AddressOf MyMenuProc)
End Sub
Public Function MyMenuProc(ByVal hWnd As Long, ByVal msg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
' If the custom menu item was selected display a message.
If msg = WM_SYSCOMMAND And wParam = IDM_MYMENUITEM Then
MsgBox "New menu item clicked!"
Exit Function
End If
' Otherwise pass the command on for normal processing.
MyMenuProc = CallWindowProc(OriginalWindowProc, hWnd, msg, _
wParam, lParam)
End Function
No comments:
Post a Comment