在控件周围绘制边框

Rom*_*key 5 c# winforms

好吧,我想在面板控件周围绘制自定义边框,我发现可以使用以下命令轻松实现

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);
Run Code Online (Sandbox Code Playgroud)

但是,此方法和我尝试过的所有其他方法实际上在面板内绘制边框,因此当我将某些控件停靠在其中时,该控件会隐藏边框。

在此输入图像描述

所以我想知道有没有办法在控件之外绘制边框来避免这个问题?

Kin*_*ing 1

有几种解决方案,但我认为这是最简单的解决方案,您必须确保将面板放置在另一个容器上,为其外边框留出足够的空间。

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();
   }
}
Run Code Online (Sandbox Code Playgroud)

请注意,边框绘制代码现在必须在面板的父级上绘制,您必须相应地调整边框矩形(它当然比面板内绘制的边框大)。

另请注意,由于在父级上绘图,因此当面板的大小或位置发生更改时,我们需要使父级无效才能正确重绘。该Invalidate()方法可以接受一个Rectangle只是在该矩形上无效,您可以计算要绘制的边框矩形,并传入该Invalidate方法以稍微提高绘制的性能(主要有助于防止闪烁)。