CodeItBetter Programming Another VB Programming Blog

How to Create a Menu completely at Runtime

Posted on January 4, 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 Create a Menu completely at Runtime
'In a Module:

Private 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 CreateMenu Lib "user32" () As Long
Private 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
Private Declare Function SetMenu Lib "user32" (ByVal hwnd As Long, ByVal hMenu As Long) As Long
Private Declare Function DrawMenuBar Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function CreatePopupMenu Lib "user32" () As Long
Public Declare Function GetSystemMenu Lib "user32" (ByVal hwnd As Long, _
    ByVal bRevert As Long) As Long
Private Const MF_ENABLED = &H0&
Private Const MF_POPUP = &H10&
Private Const MF_SEPARATOR = &H800&
Private Const MF_STRING = &H0&
Private Const WM_MENUSELECT = &H11F
Public Const GWL_WNDPROC = (-4)
Public lPrevWnd As Long
Public lSysMnu As Long
Public lMnu As Long
 
Public Sub CreateMenuBar()
    'Generate a Simple File Menu..
    Dim lSubMnu As Long
    Dim lRes As Long
    lMnu = CreateMenu 'Create a Menu Item
    lSubMnu = CreatePopupMenu 'Create a Popup Menu
    'Add Items to the Popup Menu
    'Each Item Requires a Unique ID to Identify it in our Menu Event
    lRes = AppendMenu(lSubMnu, MF_ENABLED Or MF_STRING, 1, ByVal "&Open")
    lRes = AppendMenu(lSubMnu, MF_ENABLED Or MF_STRING, 2, ByVal "&Save")
    lRes = AppendMenu(lSubMnu, MF_ENABLED Or MF_STRING, 3, ByVal "Save &As..")
    lRes = AppendMenu(lSubMnu, MF_ENABLED Or MF_STRING, 4, ByVal "&Exit")
    'Add the Popup Menu to the Main File Menu Item..
    lRes = AppendMenu(lMnu, MF_ENABLED Or MF_STRING Or MF_POPUP, lSubMnu, ByVal "File")
    'Assign the Menu to the Form
    lRes = SetMenu(Form1.hwnd, lMnu)
    'Draw the Menu, Only works when the Form is Visible.
    lRes = DrawMenuBar(Form1.hwnd)
End Sub
 
Public Function SubClassedForm(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, _
    ByVal lParam As Long) As Long
    Static lLastItemSelected As Long
    If Msg = &H105A Then
        'Redraw Menu
        Call SetMenu(Form1.hwnd, lMnu)
        Call DrawMenuBar(Form1.hwnd)
    ElseIf Msg = WM_MENUSELECT And lParam <> lSysMnu Then
        'Process Messages From Any of the Forms Menus, Except the System Menu
        If lParam Then
            'A Valid Item was Selected
            'Store the Index in the Static Var Until the Item is Clicked
            lLastItemSelected = wParam And 255
        Else
            'Call the MenuEvent Sub with the Last Selected Menu Item ID
            Call MenuEvent(lLastItemSelected)
            lLastItemSelected = 0
        End If
    End If
    SubClassedForm = CallWindowProc(lPrevWnd, hwnd, Msg, wParam, lParam)
End Function
 
Public Sub MenuEvent(ByVal Index As Long)
    'Menu Item Code Goes Here,
    'Each Menu Item is Identified by it's Unique Index
    With Form1
        Select Case Index
            Case 1
                .Caption = "Open"
                'Open Item Code
            Case 2
                .Caption = "Save"
                'Save Item Code
            Case 3
                .Caption = "Save As.."
                'Save As Item Code
            Case 4
                .Caption = "Exit"
                'Exit Item Code
                Unload Form1
            Case Else
                .Caption = "No Item Selected"
        End Select
    End With
End Sub
 
'In the Form:

Private Sub Form_Load()
    'Get the System Menu Handle, so we don't process it's Messages
    lSysMnu = GetSystemMenu(hwnd, 0)
    'Sub-Class the Form to Capture the Menu Messages
    lPrevWnd = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf SubClassedForm)
    'Create the Menu Completely at Runtime.
    CreateMenuBar
End Sub
 
Private Sub Form_Unload(Cancel As Integer)
    'Remove the Form Sub-Classing *** DO NOT REMOVE ***
    Call SetWindowLong(hwnd, GWL_WNDPROC, lPrevWnd)
End Sub
Filed under: Forms Leave a comment
Comments (1) Trackbacks (0)
  1. Hello,

    Trying to create a menu at runtime.

    In the function Subclassedform, the line

    ElseIf MSG = WM_MENUSELECT And LParam <> lSysmenu Then

    causes a compiler error.

    If I use

    ElseIf MSG = WM_MENUSELECT And LParam Then

    The MenuEvent is never getting called.

    Thanks bob


Leave a comment


 

No trackbacks yet.