-1

メニュー項目の子を無効にする方法のオンラインの例がいくつかありますが(たとえば、親の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プロパティを変更することはもちろん同じことです...

4

2 に答える 2

0

カスタム ToolStripMenuItem の DropDownOpening イベントをアイテムの上にマウスを置いたときに使用したときに参照された遅延を確認することができました。アイテムの上にマウスを置くと、サブメニューがなくてもサブメニューを開こうとしますそれがあなたが見ている遅延です。

代わりに OwnerChanged イベントを使用して、親アイテムがいつ DropDownOpening イベントを実行しているかを確認してみてください。

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
于 2015-02-06T01:03:56.417 に答える
0

不安でしたが、疲れました。目を覚ますと解決策が見つかりました。質問の「表示されている」というフレーズを「ペイント中」に翻訳すると、実際に明らかになりました。

Public Class SmartMenuItem
    Inherits ToolStripMenuItem

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

    Protected Overrides Sub OnPaint(e As PaintEventArgs)
        Me.Enabled = MagicEnabledFunction()
        Me.Checked = MagicCheckedFunction()
        Me.Text = MagicTextFunction()

        MyBase.OnPaint(e)
    End Sub

End Class

( AddHandler Me.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

次に、派生クラス:

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

上記のコードに含まれているコメントが、それをどのように回避したかを説明するのに役立つことを願っています。今は詳しく説明する時間がありません ;o)

于 2015-02-06T09:13:54.893 に答える