问题描述
在我的应用程序中,我有一个包含两个项目的ContextMenuStrip。 每个项目都有一个图像和一个文本。菜单项的“图像”部分与其文本之间存在一个默认的间隙,如下图所示(该间隙由红色箭头指示)。
我想通过向左移动文本来减小水平间隙,以便将间隙减小到最大1个像素。
有可能吗?如果可以,我该怎么办?
解决方法
一个示例设置,展示了如何处理通用ToolStripProfessionalRenderer和连接的ProfessionalColorTable,用于个性化ToolStrip的呈现和呈现(MenuStrip,ContextMenuStrip等)。
它组织在具有不同职责 的不同对象中:
►一个Handler类(在这里称为 MenuDesigner
),该类负责初始化其他对象(Renderer,ColorTable和Color定义)。
它还公开了允许自定义MenuItems呈现和外观的公共属性和方法。
这是应该允许消费者与之交互的唯一对象。
►从ToolStripProfessionalRenderer
派生的类对象(在这里,名为 MenuDesignerRenderer
),负责呈现菜单项,(部分或完全)覆盖默认行为。在此示例中(相对于问题),它覆盖OnRenderItemText
-基于 TextOffset
自定义属性的值和相关性来自定义MenuItems文本的位置到ToolStrip填充-和OnRenderSeparator
,这会绘制Separator
个项目(如果有)以调整到“项目文本”的新位置。
文本偏移量是使用MenuDesigner
处理程序的 TextOffset
属性设置的。
►派生出 ProfessionalColorTable
(在此命名为 MenuColorTable
)的类对象,该类对象用于覆盖的部分或全部默认属性。颜色表,它定义ToolStrip / MenuStrip的标准颜色,以分配自定义颜色。
►静态(在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)
范围内:Text的默认填充为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
({{ 1}})或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
不是魔术数字,它们是硬编码的值(在.Net源代码中可以看到)这些类的设计者设置的{之前链接的代码):e.ToolStrip.Padding.Left - 2,3,e.Item.Width,3
像素是添加到默认填充中的值,2
是分隔线在其3
像素框中的偏移量,高度。
6
►颜色表类(ProfessionalColorTable):
此类覆盖将Colors分配给MenuItems部件的属性,以设置在我们的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.Graphics.DrawLine(penForeground,e.ToolStrip.Padding.Left + TextOffset,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
类中定义的自定义颜色。
MenuRendererColors
►颜色定义类:
存储用于自定义MenusItems外观的颜色。可以根据需要使用 manager 类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
在运行时更改它们。
MenuDesigner