65.9K
CodeProject is changing. Read more.
Home

VB .NET/WinForms: Create Form's MainMenu by Load Menu from Resource-Only DLL

starIconstarIconstarIconstarIconstarIcon

5.00/5 (10 votes)

Dec 15, 2022

CPOL

2 min read

viewsIcon

27612

downloadIcon

314

Load Menu from Resource-Only DLL (created by VC++) and Set for Form As MainMenu by API Functions.

Introduction

Why do we need to load Menu from Resource-only DLL?
Resource Menus can be shared in several applications.

Use a resource-only DLL to Load Menu from that by Resource ID.

You need to know how to Create a resource-only DLL at first to make your own resource DLL and also Resource Menu.

  • After Make Resource-Only DLL Project to create Resource Menu:
    1. Choose Add->Resource Menu Item by Right-Click on the Project.

    2. Choose Menu Resource Type From Add Resource Dialog and Click on the New Button.

    3. Modify your New Resource Menu:

Background

Using API Functions:

  • Load Resource DLL by LoadLibrary API Function.
        Private Declare Function LoadLibrary Lib "kernel32" _
        Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
  • Load Resource Menu by LoadMenu API Function.
        Private Declare Function LoadMenu Lib "user32" Alias "LoadMenuA" (
        ByVal hInstance As Long,
        ByVal lpString As String) As Long
  • Use SetMenu API Function to set Form's MainMenu.
    	Public Declare Function SetMenu Lib "user32" (
        ByVal hwnd As Long,
        ByVal hMenu As Long) As Boolean
  • Create Select and Click Events and Raise those for Resource MenuItems by WndProc overridable method of the Form:
        Protected Overrides Sub WndProc(ByRef m As Message)
            Static MenuID As Long = 0
            If (m.Msg = WM_MENUSELECT) And m.LParam <> hMenu Then
                If CBool(m.LParam) Then
                    MenuID = m.WParam.ToInt64 And &HFFFF&
                    RaiseEvent MenuItemSelected(MenuID)
                Else
                    If MenuID > 0 Then
                        RaiseEvent MenuItemClicked(MenuID)
                        MenuID = 0
                    End If
                End If
            ElseIf m.Msg = WM_MENUSELECT Then
                MenuID = 0
            End If
            MyBase.WndProc(m)
        End Sub        
  • Use FreeLibrary API Function, when form is closing.
        Private Declare Function FreeLibrary Lib "kernel32.dll" (
        ByVal hLibModule As Long) As Boolean

Using the Code

You need to Define the above API Functions at Form General Declaration Section, and also these two variables: hMenu and hInstance.

Dim hMenu As Long
Dim hInstance As Long

And also needs to copy the Created Resource-Only DLL in the root(Startup) Application Directory:

Then Load that Resource DLL by using LoadLibrary API Function to set hInstance General Variable at Form Load Event:

    hInstance = LoadLibrary("Resources")

And also call resource Menu by using LoadMenu API Function via Resource ID to set hMenu General Variable:

   hMenu = LoadMenu(hInstance, "#101")

Finally, to create Form MainMenu by Resource Menu using SetMenu API Function:

   Me.Text = SetMenu(Me.Handle.ToInt64, hMenu)
Quote:
Private Sub ResourceMenu_Load(sender As Object, e As EventArgs) Handles Me.Load
    hInstance = LoadLibrary("Resources")
    hMenu = LoadMenu(hInstance, "#101")
    Me.Text = SetMenu(Me.Handle.ToInt64, hMenu)
End Sub

To know when user Select MenuItem or clicked need to use WndProc method of the Form:

  • Define this Constant at Form General Declaration Section:
        Public Const WM_MENUSELECT = &H11F
  • Create Events for Select and Click Resource MenuItems:
    	Event MenuItemSelected(ID As Integer)
        Event MenuItemClicked(ID As Integer)	
  • Type Overrides Keyword and press Space key to choose WndProc Method:

  • and use these below statements at this method:
        Protected Overrides Sub WndProc(ByRef m As Message)
            Static MenuID As Long = 0
            If (m.Msg = WM_MENUSELECT) And m.LParam <> hMenu Then
                If CBool(m.LParam) Then
                    MenuID = m.WParam.ToInt64 And &HFFFF&
                    RaiseEvent MenuItemSelected(MenuID)
                Else
                    If MenuID > 0 Then
                        RaiseEvent MenuItemClicked(MenuID)
                        MenuID = 0
                    End If
                End If
            ElseIf m.Msg = WM_MENUSELECT Then
                MenuID = 0
            End If
            MyBase.WndProc(m)
        End Sub        

But for Write and Invoke your Commands by clicking on each MenuItem, you need to know MenuItem IDs:

Go to Resource-Only DLL project and double-click on the Resources.rc to view Resources and Select Created Resource Menu, Right-click and choose Resource Symbols MenuItem:

And use each statement you want with any ID at MenuItemClicked Event Procedure:

    Private Sub ResourceMenu_MenuItemClicked(ID As Integer) Handles Me.MenuItemClicked
        Select Case ID
            Case 40001 'New
            Case 40002 'Open
            Case 40003 'Import
            Case 40004 'Export
            Case 40005 'Exit
                Application.Exit()
        End Select
    End Sub

Use FreeLibrary API Function at Form Closed Event to free the loaded dynamic-link library (DLL) module:

    Private Sub ResourceMenu_Closed(sender As Object, e As EventArgs) Handles Me.Closed
        FreeLibrary(hInstance)
    End Sub 

History

  • 15th December, 2022: Initial version