CodeItBetter Programming Another VB Programming Blog

How to add New Menu item to the Form’s Sytem Menu

Posted on January 5, 2009
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
'Forms - How to add New Menu item to the Form's Sytem Menu

'The system menu is the default pop up menu (with Restore, Move, Minimize, Maximize, etc.)
'that pops up when you right clicking on the title bar, or when you right clicking on the task bar.

'Note: to perform this task, the code below uses subclassing. If you won't close your program
'properly, it may cause your Visual Basic Environment to crash. You can close your program by
'pressing Alt +F4, clicking the form X button, or any other way, but don't close the program
'by pressing the Visual Basic Stop button.

Option Explicit
 
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 GetSystemMenu Lib "user32" (ByVal hwnd As Long, ByVal bRevert 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 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 Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSource As Any, _
    ByVal ByteLen As Long)
Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, _
    ByVal nIndex As Long) As Long
Public Declare Function EnableMenuItem Lib "user32" (ByVal hMenu As Long, ByVal wIDEnableItem As Long, _
    ByVal wEnable As Long) As Long
Public Const GWL_WNDPROC = (-4)
Public Const GWL_USERDATA = (-21)
Public Const SC_NEWMENU = 2
Public Const SC_MINIMIZE = &HF020
Public Const WM_SYSCOMMAND = &H112
Public Const WM_INITMENUPOPUP = &H117
Public Const BITMASK = &HFFFF0000
Public Const MF_STRING = &H0&
Public Const MF_SEPARATOR = &H800&
Public Const MF_GREYED = &H1&
 
Public Function FrmProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    'this allows each form to have its own window proc and hence to be able to
    'access its own properties in the Win Proc
    FrmProc = FrmFromHwnd(hwnd).WindowProc(hwnd, Msg, wParam, lParam)
End Function
 
Private Function FrmFromHwnd(hwnd As Long) As Object
    Dim oForm As Object
    Dim lPointer As Long
    lPointer = GetWindowLong(hwnd, GWL_USERDATA)
    CopyMemory oForm, lPointer, 4
    Set FrmFromHwnd = oForm
    CopyMemory oForm, 0&, 4
End Function
 
Private ml_OldWinProc As Long
 
Private Sub Form_Load()
    AddAboutMenu
    SubClass
End Sub
 
Private Sub Form_Unload(Cancel As Integer)
    UnSubClass
End Sub
 
Public Function WindowProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, _
    ByVal lParam As Long) As Long
    Dim lSysMenu As Long
    Select Case Msg
        Case WM_SYSCOMMAND
            'the user clicked on the new menu item
            If wParam = SC_NEWMENU Then
            'you can put here whatever you want to run when the menu is clicked
                MsgBox "You've clicked the new item"
            End If
        Case WM_INITMENUPOPUP
            'disable the menu option if the form is minimized. If you want
            'that it will be enabled, remove the lines below from "If lParam ..." till "End If"
            If lParam And BITMASK Then
                lSysMenu = GetSystemMenu(hwnd, 0)
                If wParam = lSysMenu Then
                    EnableMenuItem lSysMenu, SC_NEWMENU, ByVal IIf(WindowState = vbMinimized, MF_GREYED, 0)
                End If
            End If
    End Select
    WindowProc = CallWindowProc(ml_OldWinProc, hwnd, Msg, wParam, lParam)
End Function
 
Private Sub SubClass()
    'store object refernce so we can check its properties later
    SetWindowLong Me.hwnd, GWL_USERDATA, ObjPtr(Me)
    ml_OldWinProc = SetWindowLong(Me.hwnd, GWL_WNDPROC, AddressOf FrmProc)
End Sub
 
Private Sub UnSubClass()
    If ml_OldWinProc Then
        Call SetWindowLong(Me.hwnd, GWL_WNDPROC, ml_OldWinProc)
    End If
End Sub
 
Private Sub AddAboutMenu()
    Dim lOwnerWindowHandle As Long, lMenuHandle As Long
    lOwnerWindowHandle = Me.hwnd
    'Get system menu
    lMenuHandle = GetSystemMenu(lOwnerWindowHandle, False)
    'Add new menu item
    Call AppendMenu(lMenuHandle, MF_SEPARATOR, 0&, 0&)
    'replace the "New Item" below with the text you want to appear on the new menu item
    Call AppendMenu(lMenuHandle, MF_STRING, SC_NEWMENU, "&New Item")
End Sub

Related posts:

  1. How to Create a Menu completely at Runtime
  2. How to disable builtin right click context menu in text box
  3. How to add a minimize Button to Form that has fixed Border
  4. How to find list box item
  5. How to detect on which item the Mouse is hover on ListBox
  6. How to move a form without a title bar
  7. How to Move a Form without using its Title Bar
  8. How to create form and controls dynamically
  9. How to Set the ShowInTaskBar Property at Runtime
  10. How to create an HotKey for your application

Filed under: Forms Leave a comment
Comments (0) Trackbacks (0)

No comments yet.


Leave a comment


No trackbacks yet.