Reputation: 5269
Well, i wanted to draw a custom border around a panel control, and i found that it can be easily achieved using
ControlPaint.DrawBorder(e.Graphics, ClientRectangle,
Color.Indigo, 10, ButtonBorderStyle.Solid,
Color.Indigo, 10, ButtonBorderStyle.Solid,
Color.Indigo, 10, ButtonBorderStyle.Solid,
Color.Indigo, 10, ButtonBorderStyle.Solid);
However, this method and all the other methods i have tried actually draw the border inside the panel so when i dock some control inside it, the control hides the border.
So i wonder is there a way to draw the border outside the control to avoid this problem?
Upvotes: 5
Views: 6107
Reputation: 13198
Rather than an ugly workaround for not being able to paint outside your area, you can instead just keep things inside your border; so don't use docking, use anchor.
Ex:
Controls.Add(mScrollBar);
int borderSize = 1; // some border size
mScrollBar.SetBounds(
Right - mScrollBar.Width - borderSize, // x; from the right, the width and the border
borderSize, // y; from the top, just the border
mScrollBar.Width, // width can stay the same
Height - borderSize * 2 // height minus two borders
);
mScrollBar.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Right;
Upvotes: 0
Reputation: 63377
There are couples of solution however I think this is the simplest solution, you have to be ensure your panel is placed on another container which makes enough room for its outer border.
public class XPanel : Panel {
public XPanel(){
BorderWidth = 5;
}
Control previousParent;
public float BorderWidth {get;set;}
protected override void OnParentChanged(EventArgs e){
base.OnParentChanged(e);
if(Parent != previousParent){
if(Parent != null) Parent.Paint += ParentPaint;
if(previousParent != null) previousParent.Paint -= ParentPaint;
previousParent = Parent;
}
}
private void ParentPaint(object sender, PaintEventArgs e){
using(Pen p = new Pen(Color.Blue, BorderWidth))
using(var gp = new GraphicsPath())
{
float halfPenWidth = BorderWidth / 2;
var borderRect = new RectangleF(Left - halfPenWidth, Top - halfPenWidth,
Width + BorderWidth, Height + BorderWidth);
gp.AddRectangle(borderRect);
e.Graphics.DrawPath(p,gp);
}
}
protected override void OnSizeChanged(EventArgs e){
base.OnSizeChanged(e);
if(Parent!=null) Parent.Invalidate();
}
protected override void OnLocationChanged(EventArgs e){
base.OnLocationChanged(e);
if(Parent != null) Parent.Invalidate();
}
}
Note that the border drawing code now has to draw on the parent of your panel, you have to adjust the border Rectangle accordingly (it's of course larger than the border drawn inside your panel).
Also note that, because of drawing on the parent, when your panel's size or location is changed, we need to invalidate the parent to redraw correctly. The Invalidate()
method can accept a Rectangle
to just invalidate on that rectangle, you can calculate your border Rectangle to draw and also to pass in that Invalidate
method to improve the performance of drawing a little (mainly helpful to prevent flicker).
Upvotes: 1
Reputation: 22008
Dirty and easy solution. Based on krillgar's and King King's answers.
You can create own Panel
, which will hold another Panel
inside (create it in the constructor) and forward all ControlAdded
/ControlRemoved
to it, while positioning it perfectly inside. This way you can keep drawing border as you do now.
Upvotes: 1
Reputation: 12815
There is a BorderStyle property on the Panel control. Your options there are limited with that though.
The reason that you are losing the border that you're drawing is because what your drawing is inside the panel's space.
You have two options to get what you desire.
1) The far easiest way to get what you want would be to stack panels. Have the one in the back have a background color of whatever you want the border to be. Then put another panel inside of that panel with a border of whatever width you want the border to be. (If you want a 4px border on all sides, the "inner"/"top" panel will be 8px smaller on the width and height).
2) Add functionality to the Panel object to draw the border how you want. But this would be an awful lot of work.
Upvotes: 0