Winforms控制影响ClientRectangle的Custom Border和BorderWidth

时间:2013-12-14 03:54:01

标签: c# winforms border

我正在努力解决一个看似独特的问题......我有一个自定义控件,有两个属性(其中包括),名为 Border BorderWidth 。我注意到,设置这些值会影响控件的ClientRectangle的值。

据我所知,WinForms控件没有“Border”和“BorderWidth”属性,因此我无法无意中设置可能导致此问题的任何基本属性。这是问题......我有以下属性:

/// <summary>
/// Whether or not this control has a border
/// </summary>
[Browsable(true)]
public bool Border {
  get {
    return _border;
  }
  set {
    _border = value;
    this.Invalidate();
  }
}

/// <summary>
/// The width (in pixels) of the controls border
/// </summary>
[Browsable(true)]
public int BorderWidth {
  get {
    return _borderWidth;
  }
  set {
    if (value <= 1) value = 1;
      _borderWidth = value;
    }
  }
}

我在上面的两个setter中都设置了断点,只要执行了_border = value_borderWidth = value行,this.ClientRectangle的值就会立即更改。就好像.Net Framework正在读取这些属性的值并用于调整this.ClientRectaangle。我没有任何代码可以执行此操作,因为ClientRectangle无论如何都无法执行。

在运行第_border = value行之前(将值设置为“true”)

Border = false
BorderWidth = 1
this.ClientRectangle = {X=0 Y=0 Width=150 Height=29}

Border = true
BorderWidth = 1
this.ClientRectangle = {X=1 Y=1 Width=148 Height=27}

在运行_borderWidth = value之前(将值设置为“2”)

Border = true
BorderWidth = 1
this.ClientRectangle = {X=1 Y=1 Width=148 Height=27}

Border = true
BorderWidth = 2
this.ClientRectangle = {X=2 Y=2 Width=146 Height=25}

我不明白这是怎么可能的,因为我在Paint事件中使用this.ClientRectangle绘制边框和其他东西,我最终绘制的空间小于控件的实际大小;特别是边框不会通过以下代码绘制到控件的边缘:

private void DrawBorder(Graphics g, Rectangle r) {
    if (Border) {
        ControlPaint.DrawBorder(g, ClientRectangle, BorderColor, BorderWidth, ButtonBorderStyle.Solid,
            BorderColor, BorderWidth, ButtonBorderStyle.Solid,
            BorderColor, BorderWidth, ButtonBorderStyle.Solid,
            BorderColor, BorderWidth, ButtonBorderStyle.Solid);
        //float halfBorder = (float)BorderWidth / 2;
        //RectangleF r2 = new RectangleF(halfBorder, halfBorder, (float)r.Size.Width - halfBorder, (float)r.Size.Height - halfBorder);
        //g.DrawRectangles(new Pen(BorderColor, BorderWidth), new RectangleF[] { r2 });
    }
}

为长篇文章道歉,只是想提供尽可能多的信息,以提高获得解决方案的机会。

谢谢大家。

2 个答案:

答案 0 :(得分:0)

当绘制具有某种线宽的矩形时,我们有3种尺寸,外部尺寸等于ClientRectangle尺寸,内部尺寸2*lineWidth宽度不比ClientRectangle宽度宽并且2*lineWidth低于ClientRectangle高度。最后一个尺寸是中间/中心尺寸,宽度为lineWidth宽度小于ClientRectangle宽度,高度lineWidth低于ClientRectangle高度。您可以计算与Rectangle一起使用的确切ControlPaint.DrawBorder,如下所示:

var rect = ClientRectangle;
rect.Width -= borderWidth;
rect.Height -= borderWidth;
rect.Offset(borderWidth/2, borderWidth/2);
//then use the rect instead of the ClientRectangle 
//in your ControlPaint.DrawBorder
ControlPaint.DrawBorder(g, rect, ....

答案 1 :(得分:0)

这是 true 边框的行为方式。我的水晶球说你开始使用你在某处下载的代码开始控制它并实现了真正的边界。

寻找WndProc()的覆盖。 Windows发送WM_NCCALCSIZE消息以询问窗口以指定其边框。并发送WM_NCPAINT要求窗口绘制它们。您需要利用这些消息,并将绘制代码移动到收到WM_NCPAINT时现在的任何现有代码。或者完全删除该代码,以便您可以使用 OnPaintBackground 绘制自定义边框。您通常还需要打开ControlStyles.ResizeRedraw样式标志,以防止在控件调整大小时“涂抹”,例如,它固定在所有4个边上。