Reputation: 1296
I have created a custom class that uses an inherited panel, a picturebox and two labels that act as "icons" on a form for users to click and navigate throughout an application. I have done this because it gives a better graphical impression and is more customizable than just a button alone.
I have included a class to draw rounded rectangles from the following codeproject (they draw over the panel to make the panel look like it has rounded corners): http://www.codeproject.com/Articles/5649/Extended-Graphics-An-implementation-of-Rounded-Rec
In regards to painting, I have wired my MouseEnter and MouseLeave event to toggle a boolean and then call me.invalidate() to redraw the panel background based on the boolean set by the event. My code to redraw looks like:
If mouseoverBool Then 'class variable mouseoverBool set by mouseenter/mouseleave to true/false
Dim g As Graphics = e.Graphics
g.SmoothingMode = SmoothingMode.AntiAlias
Dim brush As New LinearGradientBrush(New Point(Me.Width / 2, 0), New Point(Me.Width / 2, Me.Height), Color.LightSteelBlue, Color.LightBlue)
g.FillRoundedRectangle(brush, 0, 0, Me.Width - 1, Me.Height, 10)
g.FillRoundedRectangle(New SolidBrush(Color.FromArgb(100, 118, 173, 218)), 0, 0, Me.Width, Me.Height, 10)
g.DrawRoundedRectangle(New Pen(ControlPaint.Light(SystemColors.InactiveBorder, 0.0F)), 0, 0, Me.Width - 1, Me.Height - 1, 10)
Else
Dim g As Graphics = e.Graphics
g.SmoothingMode = SmoothingMode.AntiAlias
Dim brush As New LinearGradientBrush(New Point(Me.Width / 2, 0), New Point(Me.Width / 2, Me.Height), SystemColors.GradientInactiveCaption, ControlPaint.Dark(SystemColors.GradientActiveCaption, 0.5F))
g.FillRoundedRectangle(brush, 0, 0, Me.Width - 1, Me.Height, 10)
g.FillRoundedRectangle(New SolidBrush(Color.FromArgb(100, 118, 173, 218)), 0, 0, Me.Width, Me.Height, 10)
g.DrawRoundedRectangle(New Pen(ControlPaint.Light(SystemColors.InactiveBorder, 0.0F)), 0, 0, Me.Width - 1, Me.Height - 1, 10)
End If
Alternatively in C#:
if (mouseoverBool) {
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
LinearGradientBrush brush = new LinearGradientBrush(new Point(this.Width / 2, 0), new Point(this.Width / 2, this.Height), Color.LightSteelBlue, Color.LightBlue);
g.FillRoundedRectangle(brush, 0, 0, this.Width - 1, this.Height, 10);
g.FillRoundedRectangle(new SolidBrush(Color.FromArgb(100, 118, 173, 218)), 0, 0, this.Width, this.Height, 10);
g.DrawRoundedRectangle(new Pen(ControlPaint.Light(SystemColors.InactiveBorder, 0f)), 0, 0, this.Width - 1, this.Height - 1, 10);
} else {
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
LinearGradientBrush brush = new LinearGradientBrush(new Point(this.Width / 2, 0), new Point(this.Width / 2, this.Height), SystemColors.GradientInactiveCaption, ControlPaint.Dark(SystemColors.GradientActiveCaption, 0.5f));
g.FillRoundedRectangle(brush, 0, 0, this.Width - 1, this.Height, 10);
g.FillRoundedRectangle(new SolidBrush(Color.FromArgb(100, 118, 173, 218)), 0, 0, this.Width, this.Height, 10);
g.DrawRoundedRectangle(new Pen(ControlPaint.Light(SystemColors.InactiveBorder, 0f)), 0, 0, this.Width - 1, this.Height - 1, 10);
}
The problem occuring is that the labels and picturebox inside the panel (all controls set to transparent background) are slow to refresh their backgrounds the first time any of the custom "icon" panels paint the background. The panel paints, then like half a second later, the backgrounds on the labels and picturebox finally updates. I assume that this is occuring because calling .invalidate() forces the custom panel to repaint, and then subsequently all the controls thereafter. I am after a 'seamless' paint where the entire control paints at once, including the labels and picturebox. How should I be attempting to achieve this?
Upvotes: 1
Views: 874
Reputation: 1296
I was using 2 labels and a picturebox in my custom panel to display text and a picture. As pointed out in the comments, you could easily just draw these items yourself (which not only is faster, but makes better sense since you have to handle all your controls mouseEnter/mouseLeave events by using controls in the first place) which stops the flicker from occuring.
Since I already have properties created to hold the image and label text (which was used with the former controls), it wass pretty easy to transition this into a paint event for my custom panel.
e.Graphics.DrawString(Me.txtHeaderDescription, New Font("Calibri", 12, FontStyle.Italic), Brushes.White, New Point(105, 15))
Dim sf As New StringFormat
sf.Alignment = StringAlignment.Near
Dim Rectf As RectangleF = New Rectangle(105, 35, 200, 75)
e.Graphics.DrawString(Me.txtDescription, New Font("Calibri", 8, FontStyle.Regular), Brushes.White, Rectf, sf)
e.Graphics.DrawImage(Me.MyImage, 5, 3, 96, 96)
Upvotes: 0