65.9K
CodeProject 正在变化。 阅读更多。
Home

VB .NET/WinForms: 通过从仅资源 DLL 加载菜单来创建窗体的 MainMenu

starIconstarIconstarIconstarIconstarIcon

5.00/5 (10投票s)

2022 年 12 月 15 日

CPOL

2分钟阅读

viewsIcon

28074

downloadIcon

366

通过 API 函数从仅资源 DLL(由 VC++ 创建)加载菜单,并将其设置为窗体的 MainMenu。

引言

为什么我们需要从仅资源 DLL 加载菜单?
资源菜单可以在多个应用程序中共享。

使用仅资源 DLL 通过资源 ID 从该 DLL 加载菜单。

您需要首先了解如何创建仅资源 DLL,以制作您自己的资源 DLL 和资源菜单。

  • 创建仅资源 DLL 项目后创建资源菜单
    1. 通过右键单击“项目”选择添加->资源菜单项

    2. 添加资源对话框中选择菜单资源类型,然后单击新建按钮

    3. 修改您的新建资源菜单

背景

使用 API 函数

  • 使用 LoadLibrary API 函数加载资源 DLL。
        Private Declare Function LoadLibrary Lib "kernel32" _
        Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
  • 使用 LoadMenu API 函数加载资源 菜单
        Private Declare Function LoadMenu Lib "user32" Alias "LoadMenuA" (
        ByVal hInstance As Long,
        ByVal lpString As String) As Long
  • 使用 SetMenu API 函数设置 FormMainMenu
    	Public Declare Function SetMenu Lib "user32" (
        ByVal hwnd As Long,
        ByVal hMenu As Long) As Boolean
  • 创建 SelectClick 事件,并通过 FormWndProc 可重写方法为这些资源 MenuItem 触发事件
        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        
  • form 关闭时,使用 FreeLibrary API 函数
        Private Declare Function FreeLibrary Lib "kernel32.dll" (
        ByVal hLibModule As Long) As Boolean

Using the Code

您需要在窗体常规声明部分定义上述 API 函数,以及这两个变量:hMenuhInstance

Dim hMenu As Long
Dim hInstance As Long

并且还需要将创建的仅资源 DLL 复制到根(启动)应用程序目录中

然后使用 LoadLibrary API 函数加载该资源 DLL,以在 Form Load 事件中设置 hInstance 常规变量

    hInstance = LoadLibrary("Resources")

并且还通过资源 ID 使用 LoadMenu API 函数调用资源 菜单,以设置 hMenu 常规变量

   hMenu = LoadMenu(hInstance, "#101")

最后,使用 SetMenu API 函数通过资源 菜单创建 Form MainMenu

   Me.Text = SetMenu(Me.Handle.ToInt64, hMenu)
引用
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

要了解用户何时选择菜单项或点击了菜单项,需要使用窗体的 WndProc 方法

  • 在窗体常规声明部分定义此常量
        Public Const WM_MENUSELECT = &H11F
  • 为选择和点击资源菜单项创建事件
    	Event MenuItemSelected(ID As Integer)
        Event MenuItemClicked(ID As Integer)	
  • 键入 Overrides 关键字并按空格键选择 WndProc 方法

  • 并在该方法中使用以下语句
        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        

但是要通过单击每个 MenuItem 来编写和调用您的命令,您需要知道 MenuItem ID

转到仅资源 DLL 项目并双击 Resources.rc 以查看资源并选择创建的资源菜单,右键单击并选择资源符号 菜单项

并在 MenuItemClicked 事件过程中使用您想要的每个语句和任何 ID

    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

在窗体关闭事件中使用 FreeLibrary API 函数以释放加载的动态链接库 (DLL) 模块

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

历史

  • 2022 年 12 月 15 日:初始版本
© . All rights reserved.