Borders around ScrollableControl
Hi!
I'm trying to create a new control deriving from ScrollableControl. Now I'd like to add a nice 3d-border around the entire control, but I can't seem to limit the area that the autoscroll feature uses so that it doesn't include the border. How do I do this?
Override the DisplayRectangle property. Try something like:
public override Rectangle DisplayRectangle {
get {
int borderWidth = 3;
Rectangle clientRect = ClientRectangle;
Rectangle displayRect = new Rectangle(borderWidth, borderWidth, clientRect.Width - borderWidth, clientRect.Height - borderWidth);
return displayRect;
}
}
- mike
How annoying, it seemed like a very good idea, but I couldn't make it work..
Try this for example, the scrollbars still paints straight over the border.
public class TestControl : ScrollableControl
{
private int borderWidth;
public TestControl()
{
borderWidth = 3;
}
public override Rectangle DisplayRectangle
{
get
{
Rectangle clientRect = base.DisplayRectangle;
Rectangle displayRect = new Rectangle(borderWidth, borderWidth, clientRect.Width - borderWidth, clientRect.Height - borderWidth);
return displayRect;
}
}
protected override void OnLayout(LayoutEventArgs e)
{
this.AutoScrollMinSize = new Size(400, 500);
base.OnLayout(e);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
Rectangle clip = e.ClipRectangle;
PaintBorder(g, clip);
}
protected void PaintBorder(Graphics g, Rectangle clip)
{
ControlPaint.DrawBorder3D(g,0,0,Width,Height,Border3DStyle.Sunken, Border3DSide.All);
}
}
I tried to put a breakpoint in the DisplayRectangle property, and it seems like it is actually never invoked..
/Anders
So I played with this a bit, and here's what i've come up with. Is this closer to what you're looking for?public class TestControl : ScrollableControl
{
private Size borderSize;
public TestControl()
{
this.SetStyle(ControlStyles.ResizeRedraw, true);
borderSize = new Size();
borderSize.Width = SystemInformation.VerticalScrollBarWidth;
borderSize.Height = SystemInformation.HorizontalScrollBarHeight;
}
protected override void OnLayout(LayoutEventArgs e)
{
this.AutoScrollMinSize = new Size(400, 500);
base.OnLayout(e);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
Rectangle clip = e.ClipRectangle;
PaintBorder(g, clip);
}
protected void PaintBorder(Graphics g, Rectangle clip)
{
ControlPaint.DrawBorder3D(g,0,0,Width - borderSize.Width,Height - borderSize.Height,Border3DStyle.Sunken, Border3DSide.All);
}
}
- mike
Well, not exactly. I'd like the border to lie around the scrollbars as well, not within. One problem with having them inside the scrollable area (besides that it doesn't look as good) is that the routine that redraws the control when using the scrollbars tries to be smart and copies the contents of the scrolled part in order to avoid repainting it. When the border is inside the scrollable area it is copied as well (if you try the above code, you'll notice this behaviour when scrolling). Sure, you could probably override this behaviour, but I still have my hopes that there is a better way..
What annoys me the most is that the Panel control somehow manages to do this (and it is, as far as I can see, derived from ScrollableControl). Perhaps I should simply swallow my pride and try to use Panel as the base class, but somehow it doesn't feel right.
A few things. First off, if you are painting your own border, regardless whether the bottom and right are inside or outside of the scrollbars, you will still have the scrolling redraw problem.
So I went and looked at what our Panel does, and it relies on Windows to draw the border. Basically, just override CreateParams, call the base version to get a CreateParams object and then or in the WS_EX_CLIENTEDGE flag to the ExStyle property. This is for a 3d border. For a fixed border or in the WS_BORDER flag to the Style property.
I think this is your best bet, but honestly, it is a bit of reinventing the wheel. Panel is a very thin wrapper over ScrollableControl. It doesn't add much, and hence wouldn't add much weight. Unless you're a hardcore OO purist, the effort to draw borders yourself probably isn't worth the time.
- mike
ok, thank's alot. I'll do that!