Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net 如何在显示ToolStripMenuItem时禁用或(取消)检查ToolStripMenuItem?_Vb.net_Toolstripmenu - Fatal编程技术网

Vb.net 如何在显示ToolStripMenuItem时禁用或(取消)检查ToolStripMenuItem?

Vb.net 如何在显示ToolStripMenuItem时禁用或(取消)检查ToolStripMenuItem?,vb.net,toolstripmenu,Vb.net,Toolstripmenu,关于如何禁用菜单项的子菜单项(例如,使用父菜单项的DropDownOpening事件),在线上有几个示例,但我想创建一个继承ToolStripMenuItem的类,它可以自行决定是否应启用它 大概是这样的: Public Class SmartMenuItem Inherits ToolStripMenuItem Public Sub New(text As String) MyBase.New(text) AddHandler MyBase.V

关于如何禁用菜单项的子菜单项(例如,使用父菜单项的DropDownOpening事件),在线上有几个示例,但我想创建一个继承ToolStripMenuItem的类,它可以自行决定是否应启用它

大概是这样的:

Public Class SmartMenuItem
    Inherits ToolStripMenuItem

    Public Sub New(text As String)
        MyBase.New(text)
        AddHandler MyBase.VisibleChanged, AddressOf enableSelf
    End Sub

    Private Sub enableSelf(sender As Object, e As System.EventArgs)
        Me.Enabled = MagicFunctionBooleanResult()
    End Sub

End Class
但是VisibleChanged事件没有像我希望的那样工作,我也找不到任何其他事件

我还尝试了项目本身的DropDownOpening事件,但这只会在相当长的时间内触发,因此,如果用户足够快,他们仍然可以在项目显示后单击它

这似乎是一个非常明显的特征,我担心我遗漏了一些东西…很明显

有什么想法吗


编辑:更改Checked属性当然是同一件事…

当您将鼠标悬停在项目上时,使用自定义工具StripMenuItem的DropDownOpen事件时,我确实看到了您引用的延迟。当您将鼠标移到该项上时,它将尝试打开任何子菜单,即使它没有任何子菜单。这就是你看到的延迟

尝试改用OwnerChanged事件来了解父项何时执行DropDownOpen事件:

Public Class SmartMenuItem
  Inherits ToolStripMenuItem

  Public Sub New(text As String)
    MyBase.New(text)
  End Sub

  Private Sub SmartMenuItem_OwnerChanged(sender As Object, e As EventArgs) _
                                         Handles Me.OwnerChanged
    If Me.OwnerItem IsNot Nothing Then
      Dim dropMenu As ToolStripMenuItem = TryCast(Me.OwnerItem, ToolStripMenuItem)
      If dropMenu IsNot Nothing Then
        AddHandler dropMenu.DropDownOpening, Sub() Me.Enabled = MagicBooleanResult()
      End If
    End If
  End Sub
End Class

我很着急,但很累。醒来后,我发现了解决方案,当我将问题中的“显示”一词翻译为“在油漆上”时,这一点就显得显而易见了:

通过重写事件处理函数(而不是使用AddHandler Me.Paint),可以确保在基类处理Paint事件之前执行自定义代码,这是更改显示相关属性(例如启用、选中、文本)的最佳机会

更新:在我的项目中使用了上述技术之后,我得到了一个基类,它消除了初始解决方案中的一个大缺点:即使项目被禁用,快捷键仍然会触发项目的单击事件

首先,基类:

Public Class MenuItem
    Inherits ToolStripMenuItem

    Public Delegate Sub ClickDelegate()

    Public Sub New(text As String, shortcut As Windows.Forms.Keys, clickCallback As ClickDelegate)
        MyBase.New(text)

        AddHandler Me.Click, Sub(sender As Object, e As System.EventArgs)
                                 If Me.enabledCallback Then
                                     'NOTE: shortcut keys trigger the event even, if the item is not enabled; so check here to prevent their execution
                                     clickCallback.Invoke()
                                 End If
                             End Sub


        If shortcut <> Keys.None Then
            Me.ShortcutKeys = shortcut
            Me.ShowShortcutKeys = True
        End If
    End Sub

    Protected Overrides Sub OnPaint(e As PaintEventArgs)
        'Store the current Enabled state before painting
        Dim _enabled As Boolean = Me.Enabled

        'Set Enabled/Checked according to the callbacks
        Me.Enabled = enabledCallback()
        Me.Checked = checkedCallback()

        'Paint the item
        MyBase.OnPaint(e)

        'Restore Enabled
        Me.Enabled = _enabled


        'NOTES:
        '- If the native Enabled-property is not disabled, then the mechanism above allows the item to always respond to shortcut keys.
        '- In the lamda click handler (which is also called when a shortcut is used) the enabledCallback will be checked to verify
        '  that the clickCallback should really be executed.
        '- This way, if the criteria for enabling/disabling the item (coded in enabledCallback) change, the shortcut keys will work as expected.
        '- Otherwise the enabled state would only be refreshed on paint and, if enabledCallback() = false, then the shortcut keys could not
        '  be used (until the item is painted again).
        '- Query Me.Enabled (or MyBase.enabledCallback) within the enabledCallback override to allow for enabling/disabling regardless of
        '  the criteria coded in the callback.
        '- A similar mechanism for Checked is not implemented, assuming the property is only relevant for painting and is not queried anywhere else.


    End Sub
    Protected Overridable Function enabledCallback() As Boolean
        Return Me.Enabled
    End Function

    Protected Overridable Function checkedCallback() As Boolean
        Return Me.Checked
    End Function
End Class
公共类菜单项
继承ToolStripMenuItem
公共委托子单击委托()
Public Sub New(文本为字符串,快捷方式为Windows.Forms.Keys,clickCallback为ClickDelegate)
MyBase.New(文本)
AddHandler Me.Click,Sub(发送者作为对象,e作为System.EventArgs)
如果是我,那么启用回调
'注意:如果项目未启用,快捷键甚至会触发事件;所以请检查这里,以防止他们被处决
单击callback.Invoke()
如果结束
端接头
如果是快捷键,则为无
Me.ShortcutKeys=快捷方式
Me.ShowShortcutKeys=True
如果结束
端接头
受保护的覆盖子OnPaint(如PaintEventArgs)
'在绘制前存储当前启用状态
Dim _启用为布尔值=Me.enabled
'根据回调设置启用/检查
Me.Enabled=enabledCallback()
Me.Checked=checkedCallback()
"画一画,
MyBase.OnPaint(e)
'已启用还原
Me.Enabled=\u Enabled
'注:
“-如果未禁用本机启用属性,则上述机制允许项目始终响应快捷键。
“-在lamda单击处理程序中(使用快捷方式时也会调用该处理程序),将选中enabledCallback以进行验证
'这意味着应该真正执行clickCallback。
“-这样,如果启用/禁用项目的条件(在enabledCallback中编码)更改,快捷键将按预期工作。
“-否则,启用状态将仅在绘制时刷新,如果enabledCallback()=false,则无法使用快捷键
“必须使用(直到项目再次喷漆)。
'-Query Me.Enabled(或MyBase.enabledCallback)在enabledCallback覆盖中允许启用/禁用
'回调中编码的条件。
“-未实现类似的Checked机制,假设该属性仅与绘制相关,且不在其他任何地方查询。
端接头
受保护的可重写函数enabledCallback()为布尔值
返回我。启用
端函数
受保护的可重写函数checkedCallback()为布尔值
还我,检查过了
端函数
末级
第二,派生类:

Public Class SelectionMenuItem
    Inherits Wd.Menu.MenuItem

    Public Sub New(text As String, shortCut As Windows.Forms.Keys, callback As MenuItem.ClickDelegate, minCount As Integer, Optional maxCount As Integer = 1000)
        MyBase.New(text, shortCut, callback)

        _minCount = minCount
        _maxCount = maxCount
    End Sub

    Private _minCount As Integer
    Private _maxCount As Integer

    Protected Overrides Function enabledCallback() As Boolean
        Return (Magic.Selection.Count >= _minCount) AndAlso (Magic.Selection.Count <= _maxCount)
    End Function
End Class
公共类选择菜单项
继承Wd.Menu.MenuItem
Public Sub New(文本为字符串,快捷方式为Windows.Forms.Keys,回调为MenuItem.ClickDelegate,minCount为整数,可选maxCount为整数=1000)
MyBase.New(文本、快捷方式、回调)
_minCount=minCount
_maxCount=maxCount
端接头
私有_minCount为整数
Private\u maxCount为整数
受保护的重写函数enabledCallback()为布尔值

Return(Magic.Selection.Count>=\u minCount)和also(Magic.Selection.Count)它是下拉打开的。天知道你做了什么使它“慢”。MessageBox不是一个调试器。延迟是为了防止在拖动(悬停)浏览菜单时出现令人烦恼的子项像许多用户一样,将鼠标放在每个项目上。我想知道为什么这个问题被否决了…任何关于我做错了什么的提示或关于如何防止否决的建议都会很好。否决仙女来拜访了。
Public Class SelectionMenuItem
    Inherits Wd.Menu.MenuItem

    Public Sub New(text As String, shortCut As Windows.Forms.Keys, callback As MenuItem.ClickDelegate, minCount As Integer, Optional maxCount As Integer = 1000)
        MyBase.New(text, shortCut, callback)

        _minCount = minCount
        _maxCount = maxCount
    End Sub

    Private _minCount As Integer
    Private _maxCount As Integer

    Protected Overrides Function enabledCallback() As Boolean
        Return (Magic.Selection.Count >= _minCount) AndAlso (Magic.Selection.Count <= _maxCount)
    End Function
End Class