This issue has seriously frustrated me.
I am overridding OnPaintBackground to draw a gradient background in my custom control.
It resizes great - very smooth, no flicker.
When I try to move another window across it, it will repaint itself repeatedly... but it will repaint the area that was hidden by the window as if it was the entire control. So if I am starting the gradient from blue to green...When I move a window over half of the control, and then start moving it off, it will start painting the blue in the middle of the control. So after I have the window off the control...the first half of the control looks normal. The second half looks like the beginning of the control drawn over itself about a million times.
I hope this makes sense
Another issue(maybe a clue!)... I am getting a ton of "Out Of Memory" exceptions during the OnPaint/OnPaintBackground (only when I am moving a window over the control). Other than that I do not get Exceptions.
(Yes I Disposed of all of my drawing objects at the end of the OnPaint method.)
I have set all of my styles.
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
I have attempted to put my custom drawing code inside OnPaint and then instead in OnPaintBackground. Both cause the same problem.
I tried getting the Control's ClientRectangle instead of getting the e.ClipRectangle to draw in (during the onPaint method). No Luck...
I am seriously lost here. This control has to be ready in time for our next build, and everything works great except this. If anyone has any clue to what is happening, I would very much appreciate the help. Thanks!
Rick

Custom control draws incorrectly when moving another window over it.
Matt Warren - MSFT
{
height = e.ClipRectangle.Height;
right = e.ClipRectangle.Right - 2;
top = e.ClipRectangle.Top + 2;
left = e.ClipRectangle.Left + 1;
bottom = e.ClipRectangle.Bottom - 2;
points = new Point[]{
new Point(left, bottom),
new Point(right, bottom),
new Point(right, top+value),
new Point(right-value, top),
new Point(left + value, top),
new Point(left, top+value),
new Point(left, bottom)};
path.AddLines(points);
using (Pen pen = new Pen(Color.LightSkyBlue, .5f))
{
graphic.DrawPath(pen, path);
}
path.Dispose();
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
{
public partial class HeaderPanel : UserControl
{
private Region HeaderRegion;
private LinearGradientBrush brush;
public string Header
{
get
{
return _Header;
}
set
{
this._Header = value;
}
}
{
InitializeComponent();
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);
this.Location = new Point(10, 10);
this.Font = new Font("Verdana", 8, FontStyle.Bold);
}
{
try
{
Rectangle r = this.ClientRectangle;
int height = r.Height;
int right = r.Right - 2;
int top = r.Top + 2;
int left = r.Left + 2;
int bottom = r.Bottom - 2;
int value = 4;
Point[] points = {
new Point(left, bottom),
new Point(right, bottom),
new Point(right, top+value),
new Point(right-value, top),
new Point(left + value, top),
new Point(left, top+value),
new Point(left, bottom)};
GraphicsPath path2 = new GraphicsPath();
e.Graphics.DrawPath(new Pen(Color.LightSkyBlue, .5f), path2);
float[] relativeIntensities = { 0.0f, 0.008f, .50f };
float[] relativePositions = { 0.0f, 0.42f, 1.0f };
blend.Factors = relativeIntensities;
blend.Positions = relativePositions;
brush.Blend = blend;
e.Graphics.FillPath(brush, path2);
brush.Dispose();
path2.Dispose();
e.Graphics.DrawString(this._Header, this.Font, new SolidBrush(Color.DarkSlateBlue), left + 10, top + (height / 2 - Font.Size / 2) - 6);
System.Diagnostics.Debug.WriteLine("onPaint");
}
catch (Exception ex)
{
}
}
}
}
//CODE END
Steve Jackson
I completed agree with you PJ. That is why I tried painting using the ClientRectangle of the control to paint.
So instead of...
Rectangle rect = e.ClipRectangle;
I was using...
Rectangle rect = this.ClientRectangle;
This should get the area of the entire control Or am I doing it wrong
The exceptions are being thrown randomly! No specific line, and no specific time.
If I move the window over my control VERY slowly, no exception will be thrown. But...I was checking how many times OnPaint was being called when I move a window over my control. It was painting about 20 - 50 times per second (if not more). I am not sure if this is normal.
Oh and by the way. I have over 2gig of memory free when I get this out of memory exception. (and yes I have the .NET 1.1 patch installed)
What do you think
resolve
If you use the invalidate method inside any of your OnPaint/OnPaintBackground methods, you will have an infinite loop.
Invalidate causes OnPaint to be called, so if you put invalidate in OnPaint, it will call itself forever.
Or am I understanding this incorrectly
Fran-1980
Ah ***, it was because I was forgetting about the second declaration of the bounds!
Thanks for the help!!!!! You the man!
nicolasdiogo
You are correct, but you can better use the visable clip if you have a very large control. Remember that this doesn't work with COM Interop, if your control is used trought COM.
Than you have a memory leak.
It is normal that the Paint event is called every time when needed, so when one pixel needed a repaint, this is called.
But you should only paint the ClipRectangle, if you use a buffer! I geus you arent using a buffer, so i suggest you will implement this logic first, this will improve your speed when you have a havy painting operation.
DotNetHeaven
I am very new with using GDI+.
To give you an example of what it is supposed to look like... (if you are using windows XP)
Open MyComputer, and look at the left side of the window. Do you see those collapsable panels This header control is supposed to mimic the header style of those headers on those panels.
public partial class HeaderPanel : UserControl
{
private Region HeaderRegion;
private string _Header = "Information";
public string Header
{
get
{
return _Header;
}
set
{
this._Header = value;
}
}
public HeaderPanel()
{
InitializeComponent();
this.Location = new Point(10, 10);
this.Font = new Font("Verdana", 8, FontStyle.Bold);
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
}
protected override void OnPaintBackground(PaintEventArgs e)
{
try
{
base.OnPaintBackground(e);
Graphics graphic = e.Graphics;
int height = this.ClientRectangle.Height;
int right = this.ClientRectangle.Right - 2;
int top = this.ClientRectangle.Top + 2;
int left = this.ClientRectangle.Left + 2;
int bottom = this.ClientRectangle.Bottom - 2;
int value = 4;
Point[] points = {
new Point(left, bottom),
new Point(right, bottom),
new Point(right, top+value),
new Point(right-value, top),
new Point(left + value, top),
new Point(left, top+value),
new Point(left, bottom)};
GraphicsPath path2 = new GraphicsPath();
path2.AddLines(points);
using (GraphicsPath path = new GraphicsPath())
{
height = e.ClipRectangle.Height;
right = e.ClipRectangle.Right - 2;
top = e.ClipRectangle.Top + 2;
left = e.ClipRectangle.Left + 1;
bottom = e.ClipRectangle.Bottom - 2;
points = new Point[]{
new Point(left, bottom),
new Point(right, bottom),
new Point(right, top+value),
new Point(right-value, top),
new Point(left + value, top),
new Point(left, top+value),
new Point(left, bottom)};
path.AddLines(points);
using (Pen pen = new Pen(Color.LightSkyBlue, .5f))
{
graphic.DrawPath(pen, path);
}
path.Dispose();
}
Blend blend = new Blend();
float[] relativeIntensities = { 0.0f, 0.008f, .50f };
float[] relativePositions = { 0.0f, 0.42f, 1.0f };
blend.Factors = relativeIntensities;
blend.Positions = relativePositions;
LinearGradientBrush brush = new LinearGradientBrush(new Point(left, top + height / 2), new Point(right, top + height / 2), Color.White, SystemColors.GradientActiveCaption);
brush.Blend = blend;
graphic.FillPath(brush, path2);
brush.Dispose();
path2.Dispose();
using (SolidBrush textBrush = new SolidBrush(Color.DarkSlateBlue))
{
graphic.DrawString(this._Header, this.Font, textBrush, left + 10, top + (height / 2 - Font.Size / 2) - 6);
}
System.Diagnostics.Debug.WriteLine("onPaint");
}
catch (Exception ex)
{
}
}
}
Dan Ludwig
And for the Exception, where do you get it On a specific statement
Darren Goobey