如何覆盖WinForms文本框的首选大小?

如何覆盖WinForms文本框的首选大小?,winforms,autosize,Winforms,Autosize,NET中的文本框不允许您调整其高度(有选项) 我有一个: 示例1: 示例2: 我需要的是修正计算;覆盖.NET WinFormsTextBox控件中的错误 我创建了一个后代FixedTextBox,并尝试覆盖受保护的: 我的重写方法正在被调用,但是文本框没有改变它的“首选”大小 我还尝试覆盖受保护的DefaultSize属性: protected override Size DefaultSize { get { Size size = base.Default

NET中的
文本框
不允许您调整其高度(有选项)

我有一个:

示例1:

示例2:

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

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

我的重写方法正在被调用,但是
文本框
没有改变它的“首选”大小

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

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

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

      return size;
   }
}
它在构造期间被调用,但当“默认大小”不同时(例如,在我更改
边框样式之后),它将不再被调用,并且不会影响文本框的大小

什么是连接到.NET WinForms“AutoSize”基础结构以调整“首选”大小的正确方法

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

tl;dr:有人走进
textBox1.Height+=1
,想一想为什么它什么都不做

相关(但不同)问题
  • 提出问题,接受解决方案;与此相反,这个问题询问如何在WinForms中使用“首选大小”基础结构

  • 提到这个问题,寻找解决方案,包括让文本框重新计算其首选高度;与此相反,这个问题承认文本框无法重新计算其首选高度,即使可以,也不会有帮助,因为自动大小计算是错误的


有关SO问题,请参见菲尔·赖特的答案:

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

如果可能的话,它允许被调用控件返回它们想要的大小。但是,容器不必满足此请求的大小。例如,当控件的Dock设置为Top时,无论GetPreferredSize方法返回的值如何,宽度都将定义为包含控件的宽度。这满足了hod对于像flow layout控件这样的容器特别有用,它将一个接一个地定位每个子控件。“[Phil Wright]

这意味着此PreferredSize不会更改文本框的大小


我认为这解决了你的问题:

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;
        }
    }
}

你有没有试过做一个覆盖

protected override System.Drawing.Size DefaultSize
{ get { return new System.Drawing.Size( 145, 52 ); } }
或者你需要的任何尺寸

根据您的目的,我过去所做的事情是为某些控件创建自己的子类,并重写诸如FontSize、FontName、Size等内容,使它们都成为只读的(仅应用外部可见的“getter”)。通过这样做,任何放在具有设计时序列化的WinForms窗体上的类实例都会让我烦恼,无法从设计器中删除“只读”属性。在开发早期这样做之后,这些控件再也没有出现问题。如果我更改了它,表单将在设计器中获得最新的值/大小/字体,而无需遍历每个表单和控件的每个实例

我发现它可以很好地处理一些事情,比如只显示日期的文本框,或者日期/时间字段,另外还可以应用于标签、命令按钮和其他“通用”的elmeents。因此,在整个应用程序中,它几乎就像应用级联样式表,但在WinForms级别


只是一个想法,希望它能为您打开另一条解决困境的途径。

我找到了解决富文本框高度问题的方法。。我把它改成了通用的

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

[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 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字符串作为参数发送给方法not normal text,并确保为方法中的Richtextbox变量指定可用的宽度和高度


您可以根据您的要求使用WordWrap

我做到了;它不会影响文本框的大小。@IanBoyd,请参阅修订答案中的注释,这很好;我注意到,我随机尝试覆盖
TextBox
的随机方法可能与正确的方法没有任何关系。没有“官方”的正确方法,因为TextBox的这种行为没有文档记录。这真的只是我通过反复试验发现的一个棘手的解决办法。当文本框在多行模式下工作时,可以在设计器中使用鼠标或在属性网格中更改文本框的高度,当然也可以通过编程方式更改文本框的高度。其想法是将文本框暂时切换到多行模式,并更改高度。这一点本身不起作用,但如果同时相应地设置了最小大小,那么显然它起作用了。
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;
        }