Reputation: 1157
I am trying to create a custom control that resembles a long rectangle with rounded corners and a border. It will also contain some text, an icon and so forth, but I am having issues with the manual drawing of the control when added programmatically to my form.
The code looks like so:
Option Explicit On
Option Strict On
Imports System.Runtime.InteropServices
Imports Transitions
Imports System.Drawing.Drawing2D
Public Class AlertPanel
Private m_Radius As Integer
Private m_BorderWidth As Integer
Private m_AlertType As AlertType
Private m_Icon As Image
''' <summary>
''' Indicates a Radius of the control's corners
''' </summary>
''' <returns>The corner Radius.</returns>
Public Property Radius As Integer
Get
Return m_Radius
End Get
Set(value As Integer)
m_Radius = value
End Set
End Property
''' <summary>
''' Indicates the width to draw the outer border of the control.
''' </summary>
''' <returns>The border width.</returns>
Public Property BorderWidth As Integer
Get
Return m_BorderWidth
End Get
Set(value As Integer)
m_BorderWidth = value
End Set
End Property
''' <summary>
''' Indicates the type of Alert for the control.
''' </summary>
''' <returns>The Alert type.</returns>
Public Property AlertType As AlertType
Get
Return m_AlertType
End Get
Set(value As AlertType)
m_AlertType = value
End Set
End Property
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
End Sub
Private Sub AlertPanel_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
Dim rect As Rectangle = Me.ClientRectangle 'Drawing Rounded Rectangle
rect.X = rect.X + 1
rect.Y = rect.Y + 1
rect.Width -= 2
rect.Height -= 2
Using bb As GraphicsPath = GetPath(rect, Radius)
'Draw the background
Using br As Brush = New SolidBrush(BackColor)
e.Graphics.SmoothingMode = SmoothingMode.HighQuality
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic
e.Graphics.FillPath(br, bb)
End Using
'Draw the border
Using br As Brush = New SolidBrush(ForeColor)
rect.Inflate(-1, -1)
e.Graphics.SmoothingMode = SmoothingMode.HighQuality
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic
e.Graphics.DrawPath(New Pen(br, BorderWidth), bb)
End Using
End Using
End Sub
Protected Function GetPath(ByVal rc As Rectangle, ByVal r As Int32) As GraphicsPath
Dim x As Int32 = rc.X, y As Int32 = rc.Y, w As Int32 = rc.Width, h As Int32 = rc.Height
r = r << 1
Dim path As GraphicsPath = New GraphicsPath()
If r > 0 Then
If (r > h) Then r = h
If (r > w) Then r = w
path.AddArc(x, y, r, r, 180, 90)
path.AddArc(x + w - r, y, r, r, 270, 90)
path.AddArc(x + w - r, y + h - r, r, r, 0, 90)
path.AddArc(x, y + h - r, r, r, 90, 90)
path.CloseFigure()
Else
path.AddRectangle(rc)
End If
Return path
End Function
End Class
Then I call it like this:
Dim a As New AlertPanel
With a
.Size = New Size(400, 60)
.Location = New Point(100, 200)
.AlertType = AlertType.Major
.ForeColor = Color.Black
.BorderWidth = 1
.BackColor = Color.IndianRed
.Radius = 10
End With
Me.Controls.Add(a)
And I am left with this:
UPDATE
After some edits to my code as per Plutonix below, I now have the following results:
FINAL UPDATE
Final result looks like below. Many thanks to Plutonix for all the help!
Upvotes: 1
Views: 2171
Reputation: 1
I got rounded corners on a button control using a function that's called during the paint event.
Form1
sub headers, and paste in the belowImports System.Drawing.Drawing2D
Public Class Form1
Public Sub buttonBorderRadius(ByRef buttonObj As Object, ByVal borderRadiusINT As Integer)
Dim p As New Drawing2D.GraphicsPath()
p.StartFigure()
'TOP LEFT CORNER
p.AddArc(New Rectangle(0, 0, borderRadiusINT, borderRadiusINT), 180, 90)
p.AddLine(40, 0, buttonObj.Width - borderRadiusINT, 0)
'TOP RIGHT CORNER
p.AddArc(New Rectangle(buttonObj.Width - borderRadiusINT, 0, borderRadiusINT, borderRadiusINT), -90, 90)
p.AddLine(buttonObj.Width, 40, buttonObj.Width, buttonObj.Height - borderRadiusINT)
'BOTTOM RIGHT CORNER
p.AddArc(New Rectangle(buttonObj.Width - borderRadiusINT, buttonObj.Height - borderRadiusINT, borderRadiusINT, borderRadiusINT), 0, 90)
p.AddLine(buttonObj.Width - borderRadiusINT, buttonObj.Height, borderRadiusINT, buttonObj.Height)
'BOTTOM LEFT CORNER
p.AddArc(New Rectangle(0, buttonObj.Height - borderRadiusINT, borderRadiusINT, borderRadiusINT), 90, 90)
p.CloseFigure()
buttonObj.Region = New Region(p)
End Sub
Private Sub Button1_Paint(sender As Object, e As PaintEventArgs) Handles Button1.Paint
buttonBorderRadius(sender, 25)
End Sub
Private Sub Button2_Paint(sender As Object, e As PaintEventArgs) Handles Button2.Paint
buttonBorderRadius(sender, 50)
End Sub
End Class
Calling the function buttonBorderRadius(sender, 50)
means you can set different borderRadius's for individual buttons.
And because it uses the object, you can apply the same function to pictureboxes, and other controls (not all though).
So you can set a 10 pixel border radius with buttonBorderRadius(sender, 10)
and a 50 pixel radius like this buttonBorderRadius(sender, 50)
just change the integer as the 2nd argument in the function,
and the 1st argument has to be the object variable.
Upvotes: 0
Reputation: 100
Public Sub ctrlCornerBorder(ctrl As Control, CurveSize As Integer)
Try
Dim p As New System.Drawing.Drawing2D.GraphicsPath
p.StartFigure()
p.AddArc(New Rectangle(0, 0, CurveSize, CurveSize), 180, 90)
'p.AddLine(CurveSize, 0, ctrl.Width - CurveSize, 0)
p.AddArc(New Rectangle(ctrl.Width - CurveSize, 0, CurveSize, CurveSize), -90, 90)
'p.AddLine(ctrl.Width, CurveSize, ctrl.Width, ctrl.Height - CurveSize)
p.AddArc(New Rectangle(ctrl.Width - CurveSize, ctrl.Height - CurveSize, CurveSize, CurveSize), 0, 90)
'p.AddLine(ctrl.Width - 40, ctrl.Height, 40, ctrl.Height)
p.AddArc(New Rectangle(0, ctrl.Height - CurveSize, CurveSize, CurveSize), 90, 90)
p.CloseFigure()
ctrl.Region = New Region(p)
p.Dispose()
Catch ex As Exception
MsgBox(Err.Number & vbCrLf & Err.Description, MsgBoxStyle.Information)
End Try
Put This As A Class file And call Like This as Follows...
ctrlCornerBorder(pnlList, 15).
Here ctrlCornerBorder is our Class File name and pnlList As our Panel Name And 15 is value to be change as per your need to make curvy edge on panel...
Upvotes: 0
Reputation: 38865
I am trying to create a custom control
You didnt say whether this was subclassing a control (like Panel) or was built as a UserControl
. I am guessing the latter based on InitializeComponent()
.
The main thing seems to be that the standard Border for the UserControl
is still being painted. Add this to turn it off:
Public Sub New()
MyBase.BorderStyle = Windows.Forms.BorderStyle.None
...
You may want to hide that property so the end user cant turn it back on in Properties.
Also, with wider borders you will find that the bottom border is being clipped by one pixel (somewhat apparent in your image - the top horizontal appears thicker than the bottom one). Add this to your GetPath
method:
h As Int32 = rc.Height - 1
Result:
Also, BackColor
is inherited and applies to the entire client area, which remains a rectangle. You'll probably need to replace that as well. Leave the actual BackColor
as Transparent
, maybe hiding it that property from the user as well, and use a new FillColor
property:
' in the paint event
Using br As Brush = New SolidBrush(FillColor)
...
Using a FillColor
property and forcing BackColor
to Transparent
:
Upvotes: 2