我很着急,但也很累。醒来后,我找到了解决方案,一旦我将问题中的“显示”一词翻译为“油漆上”,这确实显得很明显:
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)