VB.NET Custom Control (custom drawing) Refresh issue
Solution 1
This is your problem:
Dim r As Rectangle = e.ClipRectangle
Change it to:
Dim r As Rectangle = Me.ClientRectangle
Solution 2
It looks to me as though your Container
class isn't painting its entire area - normally a control is responsible for painting its entire rectangle.
In order to have a control that doesn't do this - that has transparent areas (like your rounded corners) - you need to give your control the WS_EX_TRANSPARENT
property. Note that this is a Windows API subject, not a .NET one, so you're heading in the direction of some minor voodoo.
While it's written in C#, the CodeProject article Making Transparent Controls with C# and .NET 3.5 does seem directly relevant to what you're trying to achieve.
To quote that article, you first need to override the constructor of your UserControl and configure the background:
public TranspControl()
{
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
SetStyle(ControlStyles.Opaque, true);
this.BackColor = Color.Transparent;
}
Then, you need to override the CreateParams()
method to set the control style WS_EX_TRANSPARENT
:
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x20;
return cp;
}
}
Solution 3
It shouldn't be necessary to force a redraw here (under normal circumstances) since that redraw is automatically forced as soon as your control gets nudged.
However, what you need to do is clearing the background of your control before painting anything else: otherwise, your painting operation will mingle with previous painting processes. Just add an
e.Graphics.Clear(BackColor)
before your other drawing operations in the Paint
event handler. Also, consider using the OnPaint
method rather than the Paint
event since you subclass the control and don't need to resort to the Paint
event handler.
For the record, Refresh
forces a synchronous redraw which is usually not desired. Rather, use Invalidate
which enqueues the redraw request into the default window message queue.
Ropstah
Updated on June 14, 2022Comments
-
Ropstah almost 2 years
I've created a simple solution with 2 projects. The 1st project (class library) contains a custom control called Container which draws itself with rounded corners. The 2nd project (windows forms) is a test application.
If I add a Container instance to main Form in the 2nd project it shows the rounded corners nicely. Also when I run the 2nd project I can see the Container.
However when I start moving the form (click and hold the title bar), especially when I move it very fast, all the drawing is messed up, drawn over and over again but not clearing it's surface first...
I can call Container1.Refresh() in the Form1.Move event, but I don't want to set this every time because this also means I have to call Container1.Refresh() in the
Form1.Resize
event and who knows which other event...Is there an event in the Container (control) class itself where I should call Me.Refresh() or Me.Update() or Me.Invalidate() ?
For reference (Form1.vb)
Public Class Form1 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load End Sub Private Sub Form1_Move(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Move Me.Container1.Refresh() End Sub End Class
for reference (Container.vb):
Imports System.Windows.Forms Imports System.Drawing Imports System.Drawing.Drawing2D Public Class Container : Inherits Control Private _Gp As GraphicsPath Private Sub Container_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint Dim r As Rectangle = e.ClipRectangle Dim gp As New GraphicsPath Dim cs As Integer = 25 'CornerSize' r.Inflate(-5, -5) gp.AddArc(r.X, r.Y, cs, cs, 180, 90) gp.AddArc(r.X + r.Width - cs, r.Y, cs, cs, 270, 90) gp.AddArc(r.X + r.Width - cs, r.Y + r.Height - cs, cs, cs, 0, 90) gp.AddArc(r.X, r.Y + r.Height - cs, cs, cs, 90, 90) Dim t As Single = cs / 2 + r.Y gp.AddLine(r.X, r.Y + r.Height - cs, r.X, t) e.Graphics.SmoothingMode = Drawing.Drawing2D.SmoothingMode.AntiAlias e.Graphics.DrawPath(Pens.Black, gp) End Sub End Class