【问题标题】:How to add a menu item to the default right click context menu如何将菜单项添加到默认的右键单击上下文菜单
【发布时间】:2010-10-20 16:52:55
【问题描述】:

目标是创建可与 MS Access 表单上的某些控件一起使用的菜单,并能够右键单击该控件,例如在列表框和相关的上下文特定菜单弹出窗口上,如果点击,会触发一个预定义的子程序或函数。

以编程方式完成此任务的最佳方法是什么?

我正在使用 MS Access 2003,并希望使用 VBA 来执行此操作。

【问题讨论】:

  • 答案很大程度上取决于 Access 的版本。如果 A2007,一个答案,任何以前的版本,一个完全不同的答案。

标签: ms-access vba menu controls popup


【解决方案1】:

首先创建一个_MouseUp 事件以在相应控件上执行以查看是否单击了鼠标右键,如果是,则调用.ShowPopup 方法。

当然这是假设

Private Sub MyListControlName_MouseUp(ByVal Button As Integer, _
                                      ByVal Shift As Integer, _
                                      ByVal X As Long, ByVal Y As Long)

  ' Call the SetUpContextMenu function to ensure it is setup with most current context
  ' Note: This really only needs to be setup once for this example since nothing is 
  ' changed contextually here, but it could be further expanded to accomplish this
  SetUpContextMenu  
  ' See if the right mouse button was clicked
  If Button = acRightButton Then
    CommandBars("MyListControlContextMenu").ShowPopup
  End If
End Sub

由于此时命令栏MyListControlContextMenu 未定义,我在单独的模块中定义菜单如下:

Public Sub SetUpContextMenu()
  ' Note: This requires a reference to Microsoft Office Object Library
    Dim combo As CommandBarComboBox

    ' Since it may have been defined in the past, it should be deleted, 
    ' or if it has not been defined in the past, the error should be ignored

    On Error Resume Next 
    CommandBars("MyListControlContextMenu").Delete
    On Error GoTo 0

    ' Make this menu a popup menu 
    With CommandBars.Add(Name:="MyListControlContextMenu", Position:=msoBarPopup)

    ' Provide the user the ability to input text using the msoControlEdit type
    Set combo = .Controls.Add(Type:=msoControlEdit)
        combo.Caption = "Lookup Text:"           ' Add a label the user will see
        combo.OnAction = "getText"               ' Add the name of a function to call

    ' Provide the user the ability to click a menu option to execute a function    
    Set combo = .Controls.Add(Type:=msoControlButton)
        combo.BeginGroup = True                  ' Add a line to separate above group
        combo.Caption = "Lookup Details"         ' Add label the user will see
        combo.OnAction = "LookupDetailsFunction" ' Add the name of a function to call

    ' Provide the user the ability to click a menu option to execute a function        
    Set combo = .Controls.Add(Type:=msoControlButton)
        combo.Caption = "Delete Record"          ' Add a label the user will see
        combo.OnAction = "DeleteRecordFunction"  ' Add the name of the function to call

  End With

End Sub 

由于已经引用了三个函数,我们可以继续定义它们如下-

getText:注意,此选项需要同时引用命令栏菜单名称的名称以及控件标题的名称强>。

Public Function getText() As String

   getText = CommandBars("MyListControlContextMenu").Controls("Lookup Text:").Text

   ' You could optionally do something with this text here, 
   ' such as pass it into another function ...
   MsgBox "You typed the following text into the menu: " & getText

End Function

LookupDetailsFunction:在本例中,我将创建一个 shell 函数并返回文本“Hello World!”。

Public Function LookupDetailsFunction() As String

   LookupDetailsFunction = "Hello World!"

   MsgBox LookupDetailsFunction, vbInformation, "Notice!"

End Function

DeleteRecordFunction:对于这个例子,我将通过检查它是否为空来确保控件仍然有效,如果仍然有效,将执行查询以从表中删除记录。

Public Function DeleteRecordFunction() As String

   If Not IsNull(Forms!MyFormName.Controls("MyListControlName").Column(0)) Then
     Currentdb.Execute _
      "DELETE * FROM [MyTableName] " & _
      "WHERE MyKey = " & Forms!MyFormName.Controls("MyListControlName").Column(0) & ";"
     MsgBox "Record Deleted", vbInformation, "Notice!"
   End If

End Function

注意:对于 LookupDetailsFunction、DeleteRecordFunction 和 getText 函数,它们必须在公共范围内才能正常工作。

最后,最后一步是测试菜单。为此,请打开表单,右键单击列表控件并从弹出菜单中选择其中一个选项。

可选地,button.FaceID 可用于指示与菜单弹出控件的每个实例相关联的已知办公室图标。

我发现 Pillai Shyam's work 在创建 FaceID 浏览器插件时非常有帮助。

参考资料: Microsoft FaceID

【讨论】:

  • 仅供参考,我还必须在我的列表控件的_MouseUp 处理程序的If 块内添加DoCmd.CancelEvent,以防止默认的右键单击菜单出现在我的自定义菜单之后,还发现我遇到了combo As CommandBarComboBox 的类型错误,通过切换到通用的CommandBarControl 类型很容易解决。但总的来说,这是一个清晰且写得很好的答案,+1。
  • 你知道有什么机制可以更好地组织回调代码吗?我不喜欢与我的表单代码耦合的所有这些公共模块,理想情况下,我希望在表单模块中调用一个公共子模块,并且可能还将它包装在一个通用类模块中。
  • 机制?不。代码放置是的。您可以通过在使用它们的相应模块中进行必要的调用来轻松地做到这一点。这对我的用例更有效,因为其他一切都非常可控。在其他项目中,我已将代码移至调用它的区域。
  • 实际上,自从我发布该评论以来,我一直在执行一项艰巨的任务,作为一个通常使用 PHP(即带有闭包的语言)的人,我不敢相信它有多么笨重,但我已经做到了提出一个令人满意的抽象,只涉及一个模块和一个类。我仍在完善和重构,但我会将其放到网上并在完成后在此处发布链接,以供未来的访问者使用。真正棘手的一点是,当上下文菜单附加到的对象位于子窗体上时,确定获取回调正确窗体引用的方法是真正的 PITA。
  • 代码写得很好,谢谢。一切似乎都清晰而合乎逻辑。我似乎无法让它工作。我已经像柯蒂斯一样做了所有事情,并考虑了@DaveRandom 的第一条评论。显示弹出窗口,但当我单击其中一个弹出控件时没有任何反应
【解决方案2】:

试试这个

Sub Add2Menu()
  Set newItem = CommandBars("Form View Popup").Controls.Add(Type:=1)
  With newItem
    .BeginGroup = True
    .Caption = "Make Report"
    .FaceID = 0
    .OnAction = "qtrReport"
  End With
End Sub

如您所见,它将在“Form View Popup”命令栏中添加项目,当单击该项目时,它将加载程序 qtrReport

并使用此功能查看 Access 中的所有命令栏

Sub ListAllCommandBars()
For i = 1 To Application.CommandBars.Count
    Debug.Print Application.CommandBars(i).Name
Next
End Sub

【讨论】:

  • 这正是我想要的。谢谢
【解决方案3】:

为了将默认快捷菜单替换为包含默认操作和自定义操作的菜单,您必须创建一个包含默认操作的自定义快捷菜单。无法扩展默认快捷菜单。

Access 2003 及之前版本中的快捷菜单是一种特殊的工具栏。您创建它们的方式(或多或少)与创建自定义工具栏的方式相同。不过,UI 有点奇怪,因为您可以在一个特殊的地方创建它们。

要开始使用,请右键单击前端 Access MDB 中的工具栏。选择自定义。在工具栏列表中,选中快捷菜单。这将为您提供所有内置快捷菜单的列表,除了它们实际上最终看起来不像在实际使用中那样。例如,如果右键单击一个表单,你会得到这个快捷菜单:

Form Design
Datasheet View
PivotTable View
PivotChart View
Filter By Form
Apply Filter/Sort
Remove Filter/Sort
Cut
Copy
Paste
Properties

现在,快捷菜单上的这个菜单在哪里?好吧,这恰好是 FORM VIEW TITLE BAR 菜单,即使它在您单击窗体上的控件以外的任何位置时都会弹出。因此,如果这是您要更改的菜单,您可以通过向其添加菜单项来编辑它(拖放操作)。

我认为创建一个复制内置菜单并添加增强功能的自定义快捷菜单实际上更好(如上所述),因为这允许您保留 Access 默认快捷菜单,同时还拥有它的自定义版本在您需要时使用。在这种情况下,您需要启动一个新的快捷菜单,这就是 UI 很奇怪的地方:

您单击快捷菜单上的最后一个选项“自定义”。您会看到它下拉了一个占位符。您不能拖放到它。相反,您必须在主工具栏编辑窗口中单击“新建”并创建一个新的快捷工具栏(将其命名为您希望自定义快捷菜单具有的名称)。您的新工具栏现在显示在工具栏列表中。突出显示它并单击 PROPERTIES,然后将类型更改为 POPUP。这将为您提供信息警告,表明此更改将其从工具栏更改为快捷菜单。然后您可以关闭工具栏/快捷菜单的属性表,现在如果您再次选中快捷菜单并查看自定义菜单,您将看到新创建的菜单。现在,您可以将内置菜单的菜单项拖放到新菜单中——但不要将它们拖放到菜单本身上,而是拖放到菜单名称右侧 > 浮出控件中的占位符上。

然后,您可以将所需的任何选项从任何菜单或工具栏中拖放到您的自定义菜单中。

我假设您知道如何使用快捷菜单,因为它是所有表单对象的属性表的一部分。

2009 年 5 月 21 日更新: Access 2007 官方博客刚刚在Access 2007 中发了一个article on doing this programmatically。由于ribbon 界面的原因,会有一些差异,但有些东西会是一样的。

【讨论】:

  • Access 是否按照 Excel、Word 等使用 Office.CommandBar 和 Office.CommandBarButton 对象?
  • David,这对于理解 Access 如何处理命令栏非常有帮助。但是,我希望以编程方式执行您所说的操作。
  • 根据我的经验,它以编程方式可行,但相当繁琐。在 VBE 帮助中搜索“程序工具栏”并阅读那里的帮助。由于快捷菜单只是工具栏的一种形式,您可以使用相同的方法。不过,我自己不会那样做。我会创建自定义菜单,然后根据上下文显示/隐藏特定项目。
猜你喜欢
  • 1970-01-01
  • 2016-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-21
  • 1970-01-01
  • 2015-06-24
  • 1970-01-01
相关资源
最近更新 更多