如何覆盖WinForms TextBox的首选大小?

时间:2011-12-13 17:56:24

标签: winforms autosize

.NET中的TextBox不允许您调整其高度(isn't even an AutoSize选项)。

我有textbox that is cutting off the bottom of text in the box

  

示例1:

     

enter image description here

     

示例2:

     

enter image description here

我需要的是修复PreferredSize计算;覆盖.NET WinForms TextBox控件中的错误。

我创建了一个后代FixedTextBox,并尝试覆盖受保护的GetPreferredSize

public override Size GetPreferredSize(Size proposedSize)
{
   Size size = base.GetPreferredSize(proposedSize);

   if (this.BorderStyle == BorderStyle.None)
   {
      size.Height += 2;
   }

   return size;
}

我的被覆盖方法调用,但TextBox并未改变它的“首选”尺寸。

我也尝试覆盖受保护的DefaultSize属性:

protected override Size DefaultSize 
{
   get 
   { 
      Size size = base.DefaultSize;

      if (this.BorderStyle == BorderStyle.None)
      {
         size.Height += 2;
      }

      return size;
   }
}

它在构造期间被调用,但是当“默认大小”不同时(例如,在我更改BorderStyle之后),并且不会再次调用它,并且不会影响TextBox的大小。

什么是正确的方式挂钩到.NET WinForms“AutoSize”基础架构,以调整“首选”大小?

  

注意:仅仅因为我覆盖GetPreferredSize并不意味着解决方案涉及覆盖GetPreferredSize

tl; dr :有人走进textBox1.Height += 1并想出它为什么什么也没做。

相关(但不同)的问题

3 个答案:

答案 0 :(得分:1)

请参阅Phil Wright关于SO问题的答案What is the purpose of Control.GetPreferredSize method?

“Control.GetPreferredSize由容器调用,作为布局周期的一部分。

它允许被调用的控件返回他们想要的大小(如果可能)。但是,容器不必遵循此请求的大小。例如,当控件的Dock设置为Top时,无论GetPreferredSize方法返回的值如何,宽度都将定义为包含控件的宽度。这种方法对流量布局控制等容器特别有用,它将逐个定位每个子控件。“[Phil Wright]

这意味着此PreferredSize不会更改TextBox的大小。


我认为这可以解决您的问题:

public class MyTextBox : TextBox
{
    const int RequestedHight = 30;

    protected override void OnSizeChanged(EventArgs e)
    {
        base.OnSizeChanged(e);
        AssureRequestedHight();
    }

    protected override void OnCreateControl()
    {
        base.OnCreateControl();
        AssureRequestedHight();
    }

    private void AssureRequestedHight()
    {
        if (this.Size.Height != RequestedHight && !this.Multiline) {
            this.Multiline = true;
            this.MinimumSize = new Size(0, RequestedHight);
            this.Size = new Size(this.Size.Width, RequestedHight);
            this.Multiline = false;
        }
    }
}

答案 1 :(得分:0)

您是否尝试过重写

protected override System.Drawing.Size DefaultSize
{ get { return new System.Drawing.Size( 145, 52 ); } }

或您需要的任何尺寸

根据你的目的,我过去做过的事情是为某些控件创建自己的子类,并覆盖FontSize,FontName,Size等等,并将它们全部设为只读(仅应用外部可见的“吸气剂”)。通过这样做,我的类的任何实例都被置于具有设计时序列化的WinForms表单上,这样我就可以从设计器中删除“只读”属性。在开发早期这样做之后,这些控件再也没有问题。如果我更改了它,表单将在设计器中获得最新的值/大小/字体,而无需遍历控件的每个表单和每个实例。

我发现它可以很好地处理文本框,例如仅显示日期,或日期/时间字段,还可以应用于标签,命令按钮和其他“常见”目标elmeents。因此,在整个应用程序中,它几乎就像应用级联样式表,但是在WinForms级别。

只是一个想法,希望它能让你开启另一种解决困境的方法。

答案 2 :(得分:0)

我找到了Rich文本框高度问题的解决方案..我已将其修改为一般用途..

在您的应用程序中创建以下结构....

[StructLayout(LayoutKind.Sequential)]
    public struct RECT {
        public Int32 left;
        public Int32 top;
        public Int32 right;
        public Int32 bottom;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SCROLLBARINFO {
        public Int32 cbSize;
        public RECT rcScrollBar;
        public Int32 dxyLineButton;
        public Int32 xyThumbTop;
        public Int32 xyThumbBottom;
        public Int32 reserved;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
        public Int32[] rgstate;
    }

在您的类中为表单创建以下私有变量(您需要计算富文本高度)

private UInt32 SB_VERT = 1;
        private UInt32 OBJID_VSCROLL = 0xFFFFFFFB;

        [DllImport("user32.dll")]
        private static extern
            Int32 GetScrollRange(IntPtr hWnd, UInt32 nBar, out Int32 lpMinPos, out Int32 lpMaxPos);

        [DllImport("user32.dll")]
        private static extern
            Int32 GetScrollBarInfo(IntPtr hWnd, UInt32 idObject, ref SCROLLBARINFO psbi);

将以下方法添加到您的课程表格

private int CalculateRichTextHeight(string richText) {
            int height = 0;
            RichTextBox richTextBox = new RichTextBox();
            richTextBox.Rtf = richText;
            richTextBox.Height = this.Bounds.Height;
            richTextBox.Width = this.Bounds.Width;
            richTextBox.WordWrap = false;
            int nHeight = 0;
            int nMin = 0, nMax = 0;

            SCROLLBARINFO psbi = new SCROLLBARINFO();
            psbi.cbSize = Marshal.SizeOf(psbi);

            richTextBox.Height = 10;
            richTextBox.ScrollBars = RichTextBoxScrollBars.Vertical;

            int nResult = GetScrollBarInfo(richTextBox.Handle, OBJID_VSCROLL, ref psbi);
            if (psbi.rgstate[0] == 0) {
                GetScrollRange(richTextBox.Handle, SB_VERT, out nMin, out nMax);
                height = (nMax - nMin);
            }

            return height;
        }

您可能需要修改上述方法,使其按照您的要求运行... 确保将Rtf字符串作为参数发送到方法而不是普通文本,并确保为方法中的Richtextbox变量指定可用的宽度和高度...

您可以根据需要使用WordWrap ...