31

In the properties of a Panel I have set the border style to Fixed Single.
When I am running my application it has the color gray. I don't know how to change the border color.

I have tried this in the Paint event handler of the panel:

private void HCp_Paint(object sender, PaintEventArgs e)
{
    Panel p = sender as Panel;
    ControlPaint.DrawBorder(e.Graphics, p.DisplayRectangle, Color.Yellow, ButtonBorderStyle.Inset);
}
        

This displays the border like this:

Screenshot of actual result

but I want a fixed single border like this:

Screenshot of desited result

How I make the border in yellow?

yogeshkmrsoni002
  • 379
  • 3
  • 6
  • 11

6 Answers6

26

If you don't want to make a custom panel as suggested in @Sinatr's answer you can draw the border yourself:

private void panel1_Paint(object sender, PaintEventArgs e)
{
     ControlPaint.DrawBorder(e.Graphics, this.panel1.ClientRectangle, Color.DarkBlue, ButtonBorderStyle.Solid);
}
Raihan Al-Mamun
  • 337
  • 6
  • 11
  • 4
    And if you want to control the thickness: private void panel1_Paint(object sender, PaintEventArgs e) { Color col = Color.DarkBlue; ButtonBorderStyle bbs = ButtonBorderStyle.Solid; int thickness = 4; ControlPaint.DrawBorder(e.Graphics, this.panel1.ClientRectangle, col, thickness, bbs, col, thickness, bbs, col, thickness, bbs, col, thickness, bbs); } – leoinlios Jan 03 '19 at 15:55
17

You can create own Panel class and draw border in the client area:

[System.ComponentModel.DesignerCategory("Code")]
public class MyPanel : Panel
{
    public MyPanel() 
    {
        SetStyle(ControlStyles.UserPaint | ControlStyles.ResizeRedraw | ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        using (SolidBrush brush = new SolidBrush(BackColor))
            e.Graphics.FillRectangle(brush, ClientRectangle);
        e.Graphics.DrawRectangle(Pens.Yellow, 0, 0, ClientSize.Width - 1, ClientSize.Height - 1);
    }

}
Sinatr
  • 20,892
  • 15
  • 90
  • 319
  • 1
    I often put border painting in `OnPaintBackground` just to keep the frequency down. – DonBoitnott Jan 08 '14 at 19:25
  • Hi Sinatr, can you please explain where to write this code? I am not getting where to write this code I am new, pls tell the entire process. – yogeshkmrsoni002 Jan 09 '14 at 10:16
  • This solution works, but if you have a control in the panel that is set to dock.fill (for example), it overlaps on top of the rectangle and the rectangle is hidden. Anyway to set the panel's "usable space" to within the rectangle so that controls within don't overlap the rectangle? – JPProgrammer Jan 23 '15 at 06:22
  • 1
    @JPProgrammer, `Dock.Fill` can be easily replaced with anchoring (set content control location and anchor `Left | Top | Right | Bottom`), so that content will not cover drawn in client region border lines. Do not use `Dock.Fill`. – Sinatr Jan 23 '15 at 08:20
  • 1
    @Sinatr - I just gave setting the `Location` and `Anchor` a try but couldn't get it to work easily. Setting the location allows the left and top borders to show, but the right and bottom borders get overlapped. I guess I would have set the size (and continually resize the content whenever the panel resized) to get it to show the right and bottom borders? In my case I set the padding of the panel to the width of the border and got it to work (works using `Dock.Fill` or `Anchor`). – JPProgrammer Jan 23 '15 at 08:38
  • 4
    This answer is WRONG. I don't undestand why I find wo many wrong answers on Stackoverflow that have been up-voted? A border must NEVER be drawn into the CLIENT area. A border is part of the NON-CLIENT area and if you draw it into the client area it will be inside the scrollbars and when scrolling you get crap on the screen! – Elmue Dec 12 '16 at 16:50
  • 1
    @Elmue, that's called *workaround*. I agree it has drawbacks, e.g. it's necessary to take care about content not overlapping drawn border, yet it's very easy and for some it may be an acceptable solution. I guess answer was upvoted by those. – Sinatr Dec 13 '16 at 07:56
9

If you don't want to go to the trouble of sub-classing a panel, you can just create another panel 2 pixels bigger in each dimension, make it the border color and sit it directly behind the panel that needs a border. This is just a few clicks in the IDE ...

AndruWitta
  • 186
  • 3
  • 6
4

I found this post useful

I also set the padding of the panel to the thickness of the border so that controls inside the panel don't overlap the border and hide it. In my case, I wasn't using the padding otherwise so it was a good solution, but things might get more tricky if you also plan on using the padding for more than just showing the border...

Osama Rizwan
  • 615
  • 1
  • 7
  • 19
JPProgrammer
  • 486
  • 8
  • 19
  • This is great solution, but there is small problem when you have `ScrollBar` in your `Panel`. Then you should make also handler for `Scroll` event. Same like for `Resize`. – Artholl Apr 30 '15 at 12:48
  • 1
    This answer is WRONG. I don't undestand why I find wo many wrong answers on Stackoverflow that have been up-voted? A border must NEVER be drawn into the CLIENT area. A border is part of the NON-CLIENT area and if you draw it into the client area it will be inside the scrollbars and when scrolling you get crap on the screen! – Elmue Dec 12 '16 at 16:51
  • 1
    I don't know what you're on about @Elmue, but this solution worked perfectly well for me (and others too, apparently). The question is simply about how to change the border colour around a panel, nothing about non-client areas or scrollbars (btw are you trying to say all controls in the client area should never have a border around them??). If you can provide a better solution we're all ears, but I suspect you just like spouting criticism without having any better answers yourself. – JPProgrammer Dec 15 '16 at 06:04
  • 1
    Your knowledge about Windows programming is insufficient. Whatever you do in a Paint event handler or in OnPaint() will only affect the client area of the control. But the scrollbars are part of the non-client area, and a Panel is derived from ScrollableControl! So if your control has scrollbars you will paint your border INSIDE the scrollbars which is surely the wrong solution. If you want to do it correctly it is far more complicated. You will have to handle WM_NCCALCSIZE to define the width of your border and WM_NCPAINT to draw your border. Search the MSDN for that and study it! – Elmue Dec 17 '16 at 17:15
  • Sorry but Elmue is right. While this will draw a border, it will have the same effect as e.Graphics.DrawRectange() in the OnPaint() event. This is not a correct answer, placing controls inside the panel and docking items will overlap the border. – Ricky Divjakovski May 16 '23 at 02:14
1

This also worked for me:

private void HCp_Paint(object sender, PaintEventArgs e)
{
    Panel p = sender as Panel;
    ControlPaint.DrawBorder(e.Graphics, p.DisplayRectangle, Color.Yellow, ButtonBorderStyle.Solid);
}

The problem of the border style is due to the ButtomBorderStyle option "Inset". By selecting "ButtonBorderStyle.Solid" you get a single line (also dotted, dashed... are available).

For many panels, I agree that the best solution is to create your own class that inherits from Panel and overwrite the Paint method...

0

After a workaround when creating my custom panel. I was forced to apply another tweak to solve the border overlapping when the size of the child control(s) > size of the panel. In the tweak, instead of the panel drawing its border, its drawn by the parent control.

    Public Class SharpPanel : Inherits Panel
      Sub New()
        Padding = New Padding(2)
        SetStyle(ControlStyles.SupportsTransparentBackColor, True)
        SetStyle(ControlStyles.ResizeRedraw, True)
        SetStyle(ControlStyles.UserPaint, True)
        SetStyle(ControlStyles.AllPaintingInWmPaint, True)
        SetStyle(ControlStyles.ContainerControl, True)
        SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
        SetStyle(ControlStyles.ContainerControl, True)
        Width = 100
        Height = 100
        TabStop = False
     End Sub
     Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
        MyBase.OnPaint(e)
        Dim p As Control = Me.Parent
        Dim gr As Graphics = p.CreateGraphics
        Dim rec As Rectangle = Me.ClientRectangle
        If Me.VerticalScroll.Visible Then
            rec.Width = rec.Width + SystemInformation.VerticalScrollBarWidth
        End If
        If Me.HorizontalScroll.Visible Then
            rec.Height = rec.Height + SystemInformation.HorizontalScrollBarHeight
        End If
        rec.Location = Me.Location
        rec.Inflate(1, 1)
        gr.DrawRectangle(New Pen(Color.Pink), rec)
End sub
End Class
Albert Alberto
  • 801
  • 8
  • 15