【发布时间】:2021-01-15 07:42:23
【问题描述】:
在我的应用程序中,我有一个包含两个项目的 ContextMenuStrip。 每个项目都有一个图像和一个文本。菜单项的图像部分与其文本之间存在默认间隙,如下图所示(间隙由红色箭头指示)。
我想通过向左移动文本来减小水平间隙,使间隙减小到最大 1 像素。
有可能吗?如果可以,我该怎么做?
【问题讨论】:
标签: vb.net winforms graphics contextmenu contextmenustrip
在我的应用程序中,我有一个包含两个项目的 ContextMenuStrip。 每个项目都有一个图像和一个文本。菜单项的图像部分与其文本之间存在默认间隙,如下图所示(间隙由红色箭头指示)。
我想通过向左移动文本来减小水平间隙,使间隙减小到最大 1 像素。
有可能吗?如果可以,我该怎么做?
【问题讨论】:
标签: vb.net winforms graphics contextmenu contextmenustrip
显示如何处理通用ToolStripProfessionalRenderer 和连接ProfessionalColorTable 的示例设置,用于个性化工具条(MenuStrip、ContextMenuStrip 等)的呈现和呈现。
它被组织在具有不同职责的不同对象中:
▶ 一个 Handler 类(此处名为 MenuDesigner),负责初始化其他对象(Renderer、ColorTable 和 Color 定义)。
它还公开了允许自定义菜单项的呈现和方面的公共属性和方法。
它是消费者应该被允许与之交互的唯一对象。
▶ 一个派生自ToolStripProfessionalRenderer(此处名为MenuDesignerRenderer)的类对象,负责渲染菜单项,覆盖(部分或完全)默认行为。在此示例中(与问题相关),它覆盖 OnRenderItemText - 根据 TextOffset 自定义属性的值和与 ToolStrip 填充相关的值自定义 MenuItems 文本的位置- 和 OnRenderSeparator,它会绘制 Separator 项目(如果有)以调整到项目文本的新位置。
使用 MenuDesigner 处理程序的 TextOffset 属性设置文本偏移量。
▶ 一个类对象派生的ProfessionalColorTable(这里命名为MenuColorTable),用于覆盖颜色表的部分或全部默认属性定义 ToolStrip/MenuStrip 的标准颜色,以分配自定义颜色。
▶ 具有静态 (Shared) 属性的密封(在 VB.Net 中设置为 NotInheritable)类(此处命名为 MenuRendererColors)存储自定义颜色定义,它们是然后分配给ProfessionalColorTable描述的不同对象和部分。
其中一些颜色可以使用MenuDesigner 处理程序重新定义。
在示例代码中,TextColor(项目文本的颜色)和 SelectionColor(项目选择时的颜色)
● MenuDesigner 已初始化,在其构造函数中指定要自定义的 ToolStrip - 在本例中为 ContextMenuStrip。 MenuDesigner 处理程序的初始化还初始化了 Renderer 和 ColorTable。
→ 当然,可以使用任何其他 ProfessonalColorTable 派生类来代替此处介绍的类。
→ 这同样适用于定义自定义颜色的类。
● 在表单设计器中构建一个 ContextMenuStrip(这里命名为 MyContextMenuStrip),添加一个引用 MenuDesigner 的私有字段并在 Form 构造函数中对其进行初始化,传递 ContextMenuStrip 进行自定义:
Public Class SomeForm
Private toolStripDesigner As MenuDesigner = Nothing
Public Sub New()
InitializeComponent()
toolStripDesigner = New MenuDesigner(MyContextMenuStrip)
End Sub
' [...]
End Class
要更改 MenuItems 文本上的位置,请为 MenuDesigner.TextOffset 属性设置一个新值:
' Move the MenuItems Text 8 pixels to the left
toolStripDesigner.TextOffset = -8
TextOffset 属性将偏移量限制在(-8, 30) 范围内:8 像素是文本的默认填充,它与 DropDownMenus 的其他部分一样硬编码在 ToolStripDropDownMenu class 中。
这些值会在必要时进行缩放。
要更改所选项目的文本颜色和背景颜色,请设置MenuDesigner 类公开的相应属性:
' Changes the Color of Text of the MenuItems
toolStripDesigner.TextColor = Color.LightGreen
' Changes the Background Color of a selected MenuItems
toolStripDesigner.SelectionColor = Color.MidnightBlue
可以将更多属性或方法添加到MenuDesigner 处理程序,以在运行时更改自定义颜色或创建自定义行为。
这就是它的工作原理:
MenuDesigner 类:
这是处理程序类,用于初始化ToolStripProfessionalRenderer 和相关的ProfessionalColorTable。
该对象可以公开公共属性和方法,消费者可以设置/调用以修改 ColorTable 的设置和渲染器的行为。
它应该是唯一负责并允许与另一个交互的对象(它充当代理 -> 这里所有类都是public - 更容易测试 - 但都应该是internal (Friend)或private,具体取决于用例)。
Imports System.Drawing
Imports System.Windows.Forms
Public Class MenuDesigner
Private m_TextOffset As Integer = 0
Public Sub New(toolStrip As ToolStrip)
Renderer = New MenuDesignerRenderer()
If toolStrip IsNot Nothing Then
Initialize(toolStrip)
End If
End Sub
Public Sub Initialize(toolStrip As ToolStrip)
toolStrip.Renderer = Renderer
End Sub
Public ReadOnly Property Renderer As MenuDesignerRenderer
Public Property TextColor As Color
Get
Return MenuRendererColors.Text
End Get
Set
MenuRendererColors.Text = Value
End Set
End Property
Public Property SelectionColor As Color
Get
Return MenuRendererColors.Selection
End Get
Set
MenuRendererColors.Selection = Value
End Set
End Property
Public Property TextOffset As Integer
Get
Return m_TextOffset
End Get
Set
If Value <> m_TextOffset Then
m_TextOffset = Math.Min(Math.Max(-8, Value), 30)
Renderer.TextOffset = m_TextOffset
End If
End Set
End Property
End Class
渲染器类 (ToolStripProfessionalRenderer):
这些值和位置,e.ToolStrip.Padding.Left - 2, 3, e.Item.Width, 3,不是幻数,它们是硬编码值(可以在链接的 .Net 源代码中看到)之前)由这些类的设计者设置:2 像素是添加到默认填充的值,3 是分隔线在其高度为6 像素的框内的偏移量。
Imports System.Drawing
Imports System.Windows.Forms
Public Class MenuDesignerRenderer
Inherits ToolStripProfessionalRenderer
Private m_colorTable As ProfessionalColorTable = Nothing
Public Sub New()
Me.New(New MenuColorTable())
End Sub
Public Sub New(colorTable As ProfessionalColorTable)
MyBase.New(colorTable)
m_colorTable = colorTable
End Sub
Friend Property TextOffset As Integer = 0
Protected Overrides Sub OnRenderItemBackground(e As ToolStripItemRenderEventArgs)
MyBase.OnRenderItemBackground(e)
' Customize when needed
End Sub
Protected Overrides Sub OnRenderSeparator(e As ToolStripSeparatorRenderEventArgs)
MyBase.OnRenderSeparator(e)
Using penForeground As New Pen(m_colorTable.SeparatorDark, 1),
penBackground As New Pen(e.Item.BackColor, 1)
e.Graphics.DrawLine(penBackground, e.ToolStrip.Padding.Left - 2, 3, e.Item.Width, 3)
e.Graphics.DrawLine(penForeground, e.ToolStrip.Padding.Left + TextOffset, 3, e.Item.Width, 3)
End Using
End Sub
Protected Overrides Sub OnRenderItemText(e As ToolStripItemTextRenderEventArgs)
e.Item.ForeColor = MenuRendererColors.Text
Dim textRect = e.TextRectangle
textRect.Offset(TextOffset, 0)
e.TextRectangle = textRect
MyBase.OnRenderItemText(e)
End Sub
End Class
颜色表类(ProfessionalColorTable):
此类覆盖将 Colors 分配给 MenuItems 部件的属性,以设置在我们的 MenuRendererColors 类中定义的自定义颜色。
Imports System.Drawing
Imports System.Windows.Forms
Public Class MenuColorTable
Inherits ProfessionalColorTable
Public Overrides ReadOnly Property ToolStripBorder As Color = MenuRendererColors.Background
Public Overrides ReadOnly Property ToolStripGradientBegin As Color = MenuRendererColors.Background
Public Overrides ReadOnly Property ToolStripGradientEnd As Color = MenuRendererColors.Background
Public Overrides ReadOnly Property ToolStripDropDownBackground As Color = MenuRendererColors.Background
Public Overrides ReadOnly Property MenuBorder As Color = MenuRendererColors.Background
Public Overrides ReadOnly Property MenuItemBorder As Color = MenuRendererColors.ImageBand
Public Overrides ReadOnly Property MenuStripGradientBegin As Color = MenuRendererColors.Background
Public Overrides ReadOnly Property MenuStripGradientEnd As Color = MenuRendererColors.Background
Public Overrides ReadOnly Property CheckBackground As Color = MenuRendererColors.Background
Public Overrides ReadOnly Property CheckPressedBackground As Color = MenuRendererColors.Background
Public Overrides ReadOnly Property CheckSelectedBackground As Color = MenuRendererColors.Background
Public Overrides ReadOnly Property MenuItemSelected As Color = MenuRendererColors.Selection
Public Overrides ReadOnly Property MenuItemSelectedGradientBegin As Color = MenuRendererColors.Selection
Public Overrides ReadOnly Property MenuItemSelectedGradientEnd As Color = MenuRendererColors.Selection
Public Overrides ReadOnly Property MenuItemPressedGradientBegin As Color = MenuRendererColors.Selection
Public Overrides ReadOnly Property MenuItemPressedGradientEnd As Color = MenuRendererColors.Selection
Public Overrides ReadOnly Property SeparatorDark As Color = MenuRendererColors.SeparatorDark
Public Overrides ReadOnly Property SeparatorLight As Color = MenuRendererColors.SeparatorLight
Public Overrides ReadOnly Property ImageMarginGradientBegin As Color = MenuRendererColors.ImageBand
Public Overrides ReadOnly Property ImageMarginGradientMiddle As Color = MenuRendererColors.ImageBand
Public Overrides ReadOnly Property ImageMarginGradientEnd As Color = MenuRendererColors.ImageBand
Public Overrides ReadOnly Property ImageMarginRevealedGradientBegin As Color = MenuRendererColors.ImageBand
Public Overrides ReadOnly Property ImageMarginRevealedGradientMiddle As Color = MenuRendererColors.ImageBand
Public Overrides ReadOnly Property ImageMarginRevealedGradientEnd As Color = MenuRendererColors.ImageBand
End Class
颜色定义类:
存储用于自定义 MenusItems 方面的颜色。如果需要,可以在运行时使用 manager 类 MenuDesigner 更改这些。
Imports System.Drawing
Public NotInheritable Class MenuRendererColors
Public Shared Property Text As Color = Color.White
Public Shared Property Background As Color = Color.FromArgb(32, 32, 32)
Public Shared Property Selection As Color = Color.FromArgb(200, Color.DodgerBlue)
Public Shared Property ImageBand As Color = Color.FromArgb(200, 200, 200)
Public Shared Property CheckBoxBand As Color = Color.FromArgb(200, 200, 200)
Public Shared Property SeparatorDark As Color = Color.DodgerBlue
Public Shared Property SeparatorLight As Color = Color.LawnGreen
End Class
【讨论】: