Как переопределить предпочтительный размер WinForms TextBox? - PullRequest
3 голосов
/ 13 декабря 2011

A TextBox в .NET не позволяет вам регулировать его высоту (там даже не опция AutoSize).

У меня есть текстовое поле , котороеобрезает нижнюю часть текста в поле :

Пример 1:

enter image description here

Пример 2:

enter image description here

Мне нужно исправить расчет PreferredSize;переопределить ошибку в .NET WinForms TextBox control.

я создал потомка 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 ]

1 голос
/ 13 декабря 2011

См. Ответ Фила Райта на вопрос SO. Какова цель метода Control.GetPreferredSize? :

". Control.GetPreferredSize вызывается контейнерами как часть макетацикл.

Позволяет вызываемому элементу управления возвращать размер, который они хотели бы иметь, если это возможно. Контейнер не должен соблюдать этот запрошенный размер, однако. Например, когда элемент управления имеет параметр Dock Top thewidth будет определяться как ширина содержащего элемента управления независимо от значения, возвращаемого методом GetPreferredSize. Этот метод особенно полезен для контейнеров, таких как элемент управления макетом потока, который будет размещать каждый дочерний элемент управления один за другим ».[Фил Райт]

Это означает, что этот 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;
        }
    }
}
0 голосов
/ 23 февраля 2012

Я нашел решение для проблем с высотой текстового поля 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 в зависимости от ваших требований ...

0 голосов
/ 13 декабря 2011

Вы пытались сделать переопределение

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

или любой другой размер, который вам нужен

В зависимости от ваших целей в прошлом я создавал свои собственные подклассы для определенных элементов управления и переопределял такие вещи, как FontSize, FontName, Size и т. Д., И делал их все только для чтения. (только применяя внешне видимый «добытчик»). Делая это, все экземпляры моего класса, которые были помещены в форму WinForms с сериализацией во время разработки, заставили бы меня избавиться от свойства "только для чтения" от дизайнера. После этого на ранних этапах разработки у этих элементов управления больше никогда не было проблем. Если бы я когда-либо изменил его, форма получила бы новейшее значение / размер / шрифт в конструкторе без необходимости проходить через каждую форму и каждый экземпляр элемента управления.

Я считаю, что он хорошо работает с такими вещами, как текстовое поле, в котором будут отображаться только поля даты, или поля даты / времени, дополнительно применяемые к меткам, кнопкам команд и другим элементам «общего» назначения. Таким образом, во всем приложении это было почти как применение каскадной таблицы стилей, но на уровне WinForms.

Просто мысль и надежда, что она открывает вам другой подход к вашей дилемме.

...