围绕控制绘制边框

时间:2013-11-29 13:34:01

标签: 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);

然而,这个方法和我尝试过的所有其他方法实际上都是在面板内部绘制边框,所以当我在其中停靠一些控件时,控件会隐藏边框。

enter image description here

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

4 个答案:

答案 0 :(得分: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();
   }
}

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

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

答案 1 :(得分:0)

Panel控件上有BorderStyle属性。你的选择虽然有限。

您正在丢失正在绘制的边框的原因是因为您的绘图在面板的空间内。

您有两种选择可以满足您的需求。

1)获得所需内容的最简单方法是堆叠面板。让后面的那个背景颜色为你想要的边框。然后将另一个面板放在该面板内部,边框的宽度应为您想要的边框宽度。 (如果你想在所有面上都有4px边框,“内部”/“顶部”面板的宽度和高度将小8px。)

2)向Panel对象添加功能以绘制边框的方式。但这将是一项非常多的工作。

答案 2 :(得分:0)

肮脏而简单的解决方案。基于krillgar和King King的答案。

您可以创建自己的Panel,其中包含另一个Panel (在构造函数中创建)并转发所有ControlAdded / {{1}它完全定位在里面。这样你就可以像现在一样继续绘制边框。

答案 3 :(得分:0)

而不是一个丑陋的解决办法,因为你不能在你的区域外面画画,你可以改为将东西放在你的边界内;所以不要使用对接,使用锚。

例如:

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;