Scrollbar still is painted after it should be removed
- by Walter Williams
I have the following custom control and can place on a form (with AutoScroll set to true and the control anchored left, top and right).
If the form is too short for the control, the form correctly resizes the control (to make room for the scroll) and displays the scroll bar.
When the control is closed using the close glyph, the control is resized and the scroll bar is removed, but occasionally the scroll bar appears to remain painted. If the form is minimized or moved off-screen, the leftover paint is removed.
I've tried Parent.Invalidate and have toyed with it in many ways but to no avail. Any suggestions?
(Using VS 2008 Standard)
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace GroupPanelTest
{
public class GroupPanel : GroupBox
{
#region Members
private const Int32 iHeaderHeight = 20;
private Int32 iFullHeight = 200;
private Boolean bClosed = false;
private Rectangle rectCloseGlyphBounds = Rectangle.Empty;
private Boolean bIsMoveOverCloseGlyph = false;
#endregion
#region Properties
[DefaultValue(false)]
public Boolean Closed
{
get
{
return (this.bClosed);
}
set
{
if (this.bClosed != value)
{
this.bClosed = value;
if (this.bClosed)
{
this.iFullHeight = base.Height;
base.Height = GroupPanel.iHeaderHeight;
}
else
{
base.Height = this.iFullHeight;
}
foreach (Control con in base.Controls)
con.Visible = !this.bClosed;
this.Invalidate();
}
}
}
public new Int32 Height
{
get
{
return (base.Height);
}
set
{
if (value != base.Height)
{
if (this.Closed)
{
this.iFullHeight = value;
}
else
{
Int32 iOldHeight = base.Height;
base.Height = value;
}
}
}
}
[DefaultValue(typeof(Size), "350,200")]
public new Size Size
{
get
{
return (base.Size);
}
set
{
if (base.Size != value)
{
base.Size = value;
if (!this.Closed)
this.iFullHeight = value.Height;
}
}
}
[DefaultValue(typeof(Padding), "0,7,0,0")]
public new Padding Padding
{
get
{
return (base.Padding);
}
set
{
base.Padding = value;
}
}
#endregion
#region Construction
public GroupPanel ()
{
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.Selectable, true);
this.Size = new Size(350, 200);
this.Padding = new Padding(0, 7, 0, 0); // the groupbox will add to that
this.rectCloseGlyphBounds = new Rectangle(base.ClientSize.Width - 24, 2, 16, 16);
}
#endregion
#region Overrides
protected override void OnSizeChanged (EventArgs e)
{
this.rectCloseGlyphBounds = new Rectangle(base.ClientSize.Width - 24, 2, 16, 16);
base.OnSizeChanged(e);
}
protected override void OnPaint (PaintEventArgs e)
{
base.OnPaint(e); // we want all the delegates to receive the events, but we do this first so we can paint over it
Graphics g = e.Graphics;
g.FillRectangle(SystemBrushes.Window, this.ClientRectangle);
Rectangle rectTitle = new Rectangle(0, 0, this.ClientRectangle.Width, GroupPanel.iHeaderHeight);
g.FillRectangle(SystemBrushes.Control, rectTitle);
g.DrawString(this.Text, this.Font, SystemBrushes.ControlText, new PointF(5.0f, 3.0f));
if (this.bIsMoveOverCloseGlyph)
{
g.FillRectangle(SystemBrushes.ButtonHighlight, this.rectCloseGlyphBounds);
Rectangle rectBorder = this.rectCloseGlyphBounds;
rectBorder.Inflate(-1, -1);
g.DrawRectangle(SystemPens.Highlight, rectBorder);
}
using (Pen pen = new Pen(SystemColors.ControlText, 1.6f))
{
if (this.Closed)
{
g.DrawLine(pen, this.rectCloseGlyphBounds.Left + 3, this.rectCloseGlyphBounds.Top + 3, this.rectCloseGlyphBounds.Left + 8, this.rectCloseGlyphBounds.Top + 8);
g.DrawLine(pen, this.rectCloseGlyphBounds.Left + 13, this.rectCloseGlyphBounds.Top + 3, this.rectCloseGlyphBounds.Left + 8, this.rectCloseGlyphBounds.Top + 8);
g.DrawLine(pen, this.rectCloseGlyphBounds.Left + 3, this.rectCloseGlyphBounds.Top + 7, this.rectCloseGlyphBounds.Left + 8, this.rectCloseGlyphBounds.Top + 12);
g.DrawLine(pen, this.rectCloseGlyphBounds.Left + 13, this.rectCloseGlyphBounds.Top + 7, this.rectCloseGlyphBounds.Left + 8, this.rectCloseGlyphBounds.Top + 12);
}
else
{
g.DrawLine(pen, this.rectCloseGlyphBounds.Left + 3, this.rectCloseGlyphBounds.Top + 8, this.rectCloseGlyphBounds.Left + 8, this.rectCloseGlyphBounds.Top + 3);
g.DrawLine(pen, this.rectCloseGlyphBounds.Left + 13, this.rectCloseGlyphBounds.Top + 8, this.rectCloseGlyphBounds.Left + 8, this.rectCloseGlyphBounds.Top + 3);
g.DrawLine(pen, this.rectCloseGlyphBounds.Left + 3, this.rectCloseGlyphBounds.Top + 12, this.rectCloseGlyphBounds.Left + 8, this.rectCloseGlyphBounds.Top + 7);
g.DrawLine(pen, this.rectCloseGlyphBounds.Left + 13, this.rectCloseGlyphBounds.Top + 12, this.rectCloseGlyphBounds.Left + 8, this.rectCloseGlyphBounds.Top + 7);
}
}
}
protected override void OnMouseDown (MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && this.rectCloseGlyphBounds.Contains(e.Location))
this.Closed = !this.Closed; // close will call invalidate
base.OnMouseDown(e);
}
protected override void OnMouseMove (MouseEventArgs e)
{
this.bIsMoveOverCloseGlyph = this.rectCloseGlyphBounds.Contains(e.Location);
this.Invalidate(this.rectCloseGlyphBounds);
base.OnMouseMove(e);
}
#endregion
}
}