选择/检查某些项目后是否可以打开 ContextMenuStrip?
我计划使用一个简单的 ContextMenuStrip 来设置过滤器(这样我可以在菜单中或作为右键单击选项使用相同的过滤器)。
菜单列出了许多项目,我希望用户能够使用基本的检查功能来选择项目。选择完成后,用户可以单击激活过滤器选项或单击菜单外部以激活或取消过滤器。
在选择/单击事件中,菜单通常会关闭。是否可以在单击事件时保持菜单打开?
选择/检查某些项目后是否可以打开 ContextMenuStrip?
我计划使用一个简单的 ContextMenuStrip 来设置过滤器(这样我可以在菜单中或作为右键单击选项使用相同的过滤器)。
菜单列出了许多项目,我希望用户能够使用基本的检查功能来选择项目。选择完成后,用户可以单击激活过滤器选项或单击菜单外部以激活或取消过滤器。
在选择/单击事件中,菜单通常会关闭。是否可以在单击事件时保持菜单打开?
如果未来的程序员想知道如何做到这一点,这就是我想出来的。如果单击任何项目,这将不会关闭上下文菜单。创建上下文菜单条关闭事件并设置 if 语句以在关闭原因为 itemclicked 时取消关闭事件。
private void contextMenuStrip_Closing(object sender, ToolStripDropDownClosingEventArgs e)
{
if (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked)
e.Cancel = true;
}
闭幕式
设置 e.Cancel = true 使菜单保持打开状态
唯一的问题是事件不会告诉你点击了什么,所以你必须自己跟踪。在要保持菜单打开的项目的 Click 事件中设置某种标志。然后在 Closing 事件中检查标志并适当地设置 e.Cancel 。
要防止在单击项目时关闭上下文菜单,请执行以下操作。
在 ContextMenuItems 的 mousedown 事件上,将标志设置为 false,然后在上下文菜单的关闭事件中将其设置回 true。
例子:
Private blnClose As Boolean = True
Private Sub MoveUpToolStripMenuItem_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MoveUpToolStripMenuItem.MouseDown
blnClose = False
End Sub
Private Sub ContextMenuStrip1_Closing(ByVal sender As Object, ByVal e As System.Windows.Forms.ToolStripDropDownClosingEventArgs) Handles ContextMenuStrip1.Closing
e.Cancel = Not blnClose
blnClose = True
End Sub
我发现奇怪的是ContextMenuStrip.Closing
事件在事件发生之前ToolStripMenuItem.Click
触发。解决方案是在您拥有的地方使用ContextMenuStrip.ItemClicked
事件e.ClickedItem
,然后检查它是否是单击时不会关闭的项目之一ContextMenuStrip
,并设置适当的标志。然后ContextMenuStrip.Closing
你可以设置e.Cancel = true;
是否也设置了标志。不过不要忘记重置标志。
bool isRunAtStartupClicked;
private void ContextMenuStrip_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
if (e.ClickedItem == trayIcon.ContextMenuStrip.Items["miRunAtStartup"])
{
isRunAtStartupClicked = true;
}
}
private void ContextMenuStrip_Closing(object sender, ToolStripDropDownClosingEventArgs e)
{
if (e.CloseReason == ToolStripDropDownCloseReason.ItemClicked)
{
if (isRunAtStartupClicked)
{
isRunAtStartupClicked = false;
e.Cancel = true;
}
}
}
我认为 ContextMenuStrip 中没有此属性。
我们在应用程序中使用的解决方法是在 ContextMenuStrip 的单击事件上进行一些处理,然后如果我们希望上下文菜单保持打开状态,我们只需再次调用 ContextMenuStrip.Show。
如果 ContextMenuStrip 只有一个级别,这将很有效。如果有子菜单和子子菜单,那么您将不得不重新选择在单击之前打开的菜单,我不确定如何做到这一点......
OnClosing,做: e.Cancel = e.CloseReason != ToolStripDropDownCloseReason.CloseCalled; 然后当你决定关闭时,调用 Close()。
这是我的方法;它没有闪烁,而且 - 我认为 - 更灵活一些。
如果您有一组 ToolStripMenuItems 想用作切换按钮(选项开/关),试试这个:
(这ctxWildCards
只是我的ContextMenuStrip
,用于根据文件类型选择过滤器 - 用于搜索或 FileDialogs)
这是在 Visual Basic 中(显然!;),因此您可以通过编程方式或使用“Handles...”子句添加处理程序。
Private Sub OnOffToolStripMenuItem_MouseDown(sender As System.Object, e As System.Windows.Forms.MouseEventArgs)
Dim t = TryCast(sender, ToolStripMenuItem)
If Not t Is Nothing Then
'Since you may have more On/off-Items, check to see if the Owner is the ContextMenuStrip
If t.Owner Is ctxWildCards Then
' The ContextMenuStrip will stay open on Right-click, i.e. the user can check and close by clicking 'normally'
ctxWildCards.AutoClose = (e.Button = Windows.Forms.MouseButtons.Left)
End If
'Just me using a custom image for checked items.
t.Checked = Not t.Checked
t.Image = If(t.Checked, rdoImage, Nothing)
End If
End Sub
' On leaving ToolStripMenuItems of the ContextMenuStrip, allow it to AutoClose
Private Sub OnOffToolStripMenuItem_MouseLeave(sender As System.Object, e As System.EventArgs)
ctxWildCards.AutoClose = True
End Sub
我发现在不闪烁的情况下执行此操作的最佳方法是对 DropDown 菜单中的每个按钮使用 MouseDown 和 MouseLeave 事件。
例子:
Private Sub ToolStripMenuItem2_Mousedown(sender As Object, e As EventArgs) Handles ToolStripMenuItem2.MouseDown
ΥπηρεσίεςToolStripMenuItem.DropDown.AutoClose = False
End Sub
Private Sub ToolStripMenuItem2_MouseLeave(sender As Object, e As EventArgs) Handles ToolStripMenuItem2.MouseLeave
ΥπηρεσίεςToolStripMenuItem.DropDown.AutoClose = True
End Sub
我发现这对我的目的很有用。
Private Sub CM_Closing(sender As Object, e As ToolStripDropDownClosingEventArgs) Handles CM.Closing
If e.CloseReason = ToolStripDropDownCloseReason.ItemClicked Then
Dim ItemClicked As String = CM.GetItemAt(New Point(Cursor.Position.X - CM.Left, Cursor.Position.Y - CM.Top)).Name
If ItemClicked = "CMHeader" Then
e.Cancel = True
End If
End If
End Sub
您可以使用ItemClicked
来读取标签或其他一些属性。
我只想要一个简单的项目,让用户清楚地知道上下文菜单将影响哪个项目。