@ Dimitry - спасибо за информацию C #.Этот вопрос действительно помог мне начать помещать пользовательский рисунок в пользовательский элемент управления.Тем не менее, я использую Visual Basic .NET, так что здесь есть некоторые подробности и перспективы VB.Zorder, в котором графика размещена на поверхности, также имеет решающее значение.Это потому, что нет способа изменить z-порядок объектов Drawing2D, таких как .GrahicsPath и .FillRectangle;только Zorder of Controls может быть изменен.Чтобы скрыть часть существующего элемента управления и нарисовать над ним стрелку, выполните следующие действия.Весь метод должен быть помещен в событие Paint элемента управления;Затем необходимо позаботиться о том, чтобы событие Paint запускалось всякий раз, когда элемент управления перерисовывается (это уже другая история!):
- Создание объекта Graphics, присоединенного к элементу управления
- Обновите элемент управления
- Заполните прямоугольник, чтобы скрыть часть существующей информации элемента управления.
- Создайте и установите нужную форму в качестве обтравочной маски (в приведенном ниже примере кода - стрелка)
- Заполните форму желаемым цветом / изображением или любым другим необходимым размером.
В приведенном ниже примере, примененном в пользовательском элементе управления на основе ListView, создается стрелка и помещается наслева от заголовка.Он скрывает ненужный CheckBox, оставляет нужные поля зрения и выглядит так:
Прошло несколько лет с тех пор, как вы опубликовали свой вопрос и предыдущийответ.Возможно, хорошая информация, которая теперь есть в справке .NET, была добавлена с тех пор.Найдите это здесь с дополнительной информацией и ссылками.
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs) 'This is traps the default OnPaint for a Component, so it starts by calling the Base's Paint Event
MyBase.OnPaint(e)
'Add your custom paint code here - in this example, a Green Arrow
AddArrowOverHeaderCheckBox()
End Sub
Private Sub AddArrowOverHeaderCheckBox()
'Adds an Arrow that is placed over the Checkbox of the 0th row, of a ListView, (over a Row that is used as a Header in this Custom Control).
'Create a Rectangle into which to put the arrow
Dim G As Graphics = Me.CreateGraphics 'Attach a Graphics Object to the Base
Dim lvsi As ListViewItem.ListViewSubItem = Me.Items(0).SubItems(0) 'Get the first row; it is being used as a header in this case
Dim CheckBoxWidth As Integer = Me.Bounds.X 'Calculate the size of the Control's CheckBox
Dim CheckBoxHeight As Integer = lvsi.Bounds.Height
Dim InflateBy As Integer = 1 'Optional amount to resize the area in which the Arrow is to be placed
Me.Refresh() 'Refresh the ListViewTab so that it does not overpaint the arrow that is about to be created at the End Sub
Dim I As Integer = 0
I = (CheckBoxHeight + 1) Mod 2
Dim R As Rectangle = New Rectangle(lvsi.Bounds.X + Me.Margin.Left, lvsi.Bounds.Top, CheckBoxWidth, CheckBoxHeight + I) 'Make sure the height is an Odd number, to make a tidy arrow
'myBrush.Color = Color.Red
R.Inflate(InflateBy * 2, InflateBy) 'Create a covering rectangle that is larger than the CheckBox on the Left of the CheckView Item in both dimensions
Dim myBrush As New System.Drawing.SolidBrush(Me.BackColor)
G.FillRectangle(myBrush, R) 'Draw a filled Rectangle over the CheckBox in the Background colour for the ListViewTab to obscure the CheckBox
Dim RW = R.Width
Dim RH = R.Height
I = CSng(RH) * 0.5 \ 2 'Set a proportion of the arrow's width for its shaft, here 50%
If RH Mod 2 <> 0 Then RH += 1 'Ensure that the Height is an Odd number to make the Arrow axially symmetric
' 'Create a polygon in an Arrow shape that fits inside the Rectangle
Dim polyArrow As Point() = {New Point(R.X + 0, I + R.Y), New Point(R.X + RW * 0.4, I + R.Y), New Point(R.X + RW * 0.4, 0 + R.Y), New Point(R.X + RW, RH * 0.5 + R.Y),
New Point(R.X + RW * 0.4, RH + R.Y), New Point(R.X + RW * 0.4, RH - I + R.Y), New Point(R.X + 0, RH - I + R.Y)}
Dim path As New Drawing2D.GraphicsPath() 'Create a Path shaped like an Arrow & sized proportionately to the size of the required Rectangle
path.AddPolygon(polyArrow) 'Turn the Path into a polygon
Dim [reg] As New [Region](path) 'Define a Graphics Region of the shape of the Arrow
G.SetClip([reg], combineMode:=Drawing2D.CombineMode.Replace) 'Redefine the area; clipping will now prevent any drawing outside the area of the Arrow
myBrush.Color = Color.Green
G.FillRectangle(myBrush, R) 'Draw a filled Green Rectangle, clipped to the Path shape
'Dim pen As Pen = Pens.Black 'Optionally: Draw a fine boundary in black
'G.DrawPath(pen, path) 'Optionally: Draw a fine boundary in black
G.SetClip(Me.ClientRectangle) 'Remove the Clip from the Graphics area - in case G is re-used
myBrush.Dispose() 'Tidy up
G.Dispose()
End Sub