Вот пример того, что было описано в комментариях.
Текст элемента управления (здесь, полученный из стандартной метки) разделен на две части одной и той же меры. Каждый раздел может иметь свой цвет.
Активные и неактивные цвета являются настраиваемыми общедоступными свойствами, их можно установить в конструкторе
Каждый раздел отслеживается , что означает, что элемент управления знает о том, с какой стороны в данный момент находится указатель мыши.
Размер текста измеряется с помощью метода TextRenderer.MeasureText . Этот размер используется для вычисления прямоугольников, которые включают фрагменты текста.
Затем метод Rectangle.Contains ([Point]) используется для определения того, какой раздел текста при наведении курсора мыши. [Point]
рассчитывается с использованием свойства MousePosition , переведенного в клиентские координаты с использованием метода Control.PointToClient () .
Когда указатель мыши перемещается из одного раздела текста в другой (здесь можно определить только два раздела, добавив больше прямоугольников), элемент управления будет недействительным , вызывая вызов OnPaint
метод контроля.
Если указатель мыши не наведен на часть текста, вызывается base.OnPaint(e)
(что также вызывает событие Paint
), при котором текст по умолчанию отображается цветом по умолчанию.
В методе OnPaint
область Графика обрезается с помощью прямоугольников, определяющих текстовые разделы. Последующий вызов TextRenderer.DrawText , установка флага TextFormatFlags.PreserveGraphicsClipping , обрезает текст в определенной области, поэтому закрашивается только часть текста, которая умещается в области отсечения.
Метод Graphics.ExcludeClip () используется здесь для определения этих областей отсечения.
TextFormatFlags.ExternalLeading
и TextFormatFlags.TextBoxControl
также используются для репликации текстового рендеринга по умолчанию, поэтому пользовательский текст отображается в той же относительной позиции.
Вот как это ведет себя:
![Custom Control Label Split Text](https://i.stack.imgur.com/fkRkz.gif)
Пользовательский класс управления для проверки функциональности:
Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows.Forms
<DesignerCategory("Code")>
Public Class LabelSplitText
Inherits Label
Private m_Text As String = String.Empty
Private m_Sections As RectangleF() = Nothing
Private m_PaintText As Boolean = False
ReadOnly flags As TextFormatFlags = TextFormatFlags.ExternalLeading Or
TextFormatFlags.PreserveGraphicsClipping Or
TextFormatFlags.TextBoxControl
Public Sub New()
InitializeComponent()
End Sub
Private Sub InitializeComponent()
ResizeRedraw = True
End Sub
Public ReadOnly Property ActiveRectangle As RectangleF
Public ReadOnly Property ActiveSide As String = String.Empty
Public Property ActiveColor As Color = Color.White
Public Property InactiveColor As Color = Color.DimGray
Protected Overrides Sub OnLayout(e As LayoutEventArgs)
MyBase.OnLayout(e)
Me.AutoSize = False
m_Text = Me.Text
End Sub
Protected Overrides Sub OnMouseEnter(e As EventArgs)
m_Text = Me.Text
Text = String.Empty
m_PaintText = True
MyBase.OnMouseEnter(e)
Invalidate()
End Sub
Protected Overrides Sub OnMouseLeave(e As EventArgs)
m_PaintText = False
Me.Text = m_Text
MyBase.OnMouseLeave(e)
End Sub
Protected Overrides Sub OnMouseMove(e As MouseEventArgs)
MyBase.OnMouseMove(e)
Invalidate()
If m_Sections Is Nothing Then Return
Me._ActiveRectangle = If(m_Sections(0).Contains(e.Location), m_Sections(0), m_Sections(1))
End Sub
Protected Overrides Sub OnMouseClick(e As MouseEventArgs)
Me._ActiveSide = If(m_Sections(0).Contains(e.Location), "left", "right")
MyBase.OnMouseClick(e)
End Sub
Protected Overrides Sub OnPaint(e As PaintEventArgs)
If Not m_PaintText Then
MyBase.OnPaint(e)
Return
End If
Dim textSize As SizeF = TextRenderer.MeasureText(e.Graphics, m_Text, Me.Font, Me.ClientSize, flags)
m_Sections = GetTextAreaSections(textSize)
e.Graphics.ExcludeClip(Rectangle.Round(m_Sections(1)))
TextRenderer.DrawText(e.Graphics, m_Text, Me.Font, Point.Empty, GetSectionColor(0), flags)
e.Graphics.ResetClip()
e.Graphics.ExcludeClip(Rectangle.Round(m_Sections(0)))
TextRenderer.DrawText(e.Graphics, m_Text, Me.Font, Point.Empty, GetSectionColor(1), flags)
End Sub
Private Function GetSectionColor(section As Integer) As Color
Return If(m_Sections(section).Contains(PointToClient(MousePosition)),
Me.ActiveColor, Me.InactiveColor)
End Function
Private Function GetTextAreaSections(textSize As SizeF) As RectangleF()
If textSize.Width > Me.ClientSize.Width Then textSize.Width = Me.ClientSize.Width
Dim rectLeft = New RectangleF(PointF.Empty,
New SizeF(textSize.Width / 2.0F, Me.ClientSize.Height))
Dim rectRight = New RectangleF(New PointF(textSize.Width / 2.0F, 0),
New SizeF(textSize.Width / 2.0F, Me.ClientSize.Height))
Return {rectLeft, rectRight}
End Function
End Class