Строка измерения внутри элемента управления RichTextBox

Может кто-нибудь объяснить, как я могу измерить строку внутри элемента управления richtextbox, чтобы я мог автоматически изменять размер элемента управления richtextbox в соответствии с его содержимым?

Спасибо

Редактировать:

Я подумал об этом, и, поскольку ответ ниже не будет работать, если в элементе управления RichTextBox есть разные шрифты, что, если бы я мог получить верхние левые координаты элемента управления richtextbox, а затем получить нижние правые координаты самая последняя строка текста внутри rtb. По сути, это даст мне ширину и высоту строки внутри элемента управления RichTextBox. Это возможно? Или это плохая идея?


person Community    schedule 02.03.2010    source источник


Ответы (6)


Поместите следующий код в ContentsResized событие:

Private Sub rtb_ContentsResized(ByVal sender As Object, ByVal e As System.Windows.Forms.ContentsResizedEventArgs) Handles txtQuestion.ContentsResized
        Dim h = e.NewRectangle.Height, w = e.NewRectangle.Width
        h = Math.Max(h, sender.Font.Height)
        h = Math.Min(h, Me.ClientSize.Height - 10 - sender.Top)
        h += sender.Height - sender.ClientSize.Height + 1
        sender.Height = h
End Sub
person Prepmania.com    schedule 29.04.2011
comment
ContentsResized и e.NewRectangle помогли мне. Другие обычные подозреваемые, например AutoSize, GetPreferredSize не работают должным образом для RichTextBox. - person Ben Challenor; 02.03.2012
comment
Это не работает. Высота оказывается слишком короткой, и даже если я изменю ее, чтобы установить sender.Width = w, ширина вообще не изменится. - person Nick; 19.10.2018

Предполагая, что кто-то вводит в элемент управления, вы можете использовать событие, которое будет запускаться каждый раз при вводе символа (счетчик увеличения) и уменьшаться при его удалении. Это даст вам точный счет.

Редактировать:

Вы пробовали это отрегулировать по высоте?

richTextBox1.Height = (int)(1.5 * richTextBox1.Font.Height) + richTextBox1.GetLineFromCharIndex(richTextBox1.Text.Length + 1) * richTextBox1.Font.Height + 1 + richTextBox1.Margin.Vertical;

richTextBox1.SelectionStart = 0;

richTextBox1.SelectionStart = richTextBox1.Text.Length;

Или вы можете сделать это с помощью Width:

Graphics g = Graphics.FromHwnd(richTextBox1.Handle);

SizeF f = g.MeasureString(richTextBox1.Text, richTextBox1.Font);
richTextBox1.Width = (int)(f.Width)+5;
person Community    schedule 02.03.2010
comment
В настоящее время я этим и занимаюсь, хотя вы не можете учесть стили / размеры шрифтов таким образом, и в конечном итоге rtb не сможет справиться с этим, и текст будет переполняться - person ; 02.03.2010
comment
Без обид, но это дает очень уродливые результаты. Должен быть способ сделать это, чтобы не было похоже, что RichTextBox вот-вот взорвется через мой монитор. - person ; 03.03.2010
comment
Хм, вроде все работает нормально, но я не применяю никаких стилей шрифтов - person ; 03.03.2010
comment
Это может работать для простых текстовых полей, но не работает для RichTextBoxes, которые могут содержать жирные слова, использовать несколько шрифтов и несколько размеров шрифтов. - person Nick; 19.10.2018


Вы можете измерить строку, вызвав TextRenderer.MeasureText.

Однако, если текст содержит несколько шрифтов, это не сработает.

ИЗМЕНИТЬ: вы ищете _ 2_ метод.
Обратите внимание, что если есть несколько строк, вы должны взять максимум X-координат последнего символа в каждой строке.

person SLaks    schedule 02.03.2010
comment
Спасибо. Я не совсем понимаю эту страницу. Почему он рисует текст? Может ли он просто вернуть мне значение ширины и высоты, чтобы я мог сбросить размер RichTextBox на новый размер? - person ; 02.03.2010
comment
TextRenderer.MeasureText ничего не рисует; он просто возвращает размер текста в пикселях. - person SLaks; 02.03.2010

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

person Bathineni    schedule 23.02.2012
comment
Это не работает. Высота всегда оказывается слишком короткой. - person Nick; 19.10.2018

Добавьте к замечательному ответу Батинени:

Справочная информация: мне нужно было измерить высоту вывода RTF для рендеринга на бумагу, и поскольку у меня есть настраиваемые динамические верхние и нижние колонтитулы страниц, которые мне нужны для управления разбиением на страницы).

(RichTextBox.GetLineFromCharIndex подвел меня из-за сложного RTF; включая строки и таблицы с несколькими столбцами с переносом слов).

Как бы то ни было, все работало нормально, пока кто-то другой не использовал мое приложение с ужасными окнами «Сделать текст и другие элементы больше или меньше» (настройки DPI). Короче говоря, теперь, измеряя шрифты большего размера, он испортил вычисления длины страницы. (принтер по-прежнему правильно отображал текст и столбцы - теперь неправильная была только длина страниц.)

Только факторизация разницы в DPI не удалась, так как более крупный текст не помещался должным образом в исходные значения RTF tx и cellx.

Во всяком случае, на случай, если другие делают подобные сумасшедшие вещи, методом проб и ошибок были придуманы следующие (в конечном итоге очень немногие) модификации к методу Bathineni CalculateRichTextHeight:

RichTextBox richTextBox = new RichTextBox();     // same as original
int dpix = richTextBox.CreateGraphics().DpiX;    // get dpi
richTextBox.WordWrap = true;                     // I needed this, you many not
  // ... set size etc - same as original answer
richTextBox.Scale(new System.Drawing.SizeF(dpix / 96, dpix / 96));  // scale RTB
  // ...
  // 96? my original calculations based on windows default 96dpi settings.

Кажется, в остальном непонятный Control.Scale (sizef) действительно для чего-то полезен.

Примечание: при преобразовании результатов в фактические напечатанные строки (в моем случае все мои \ pard были "\ sl-240 \ slmult0", что составляет 16 (пикселей?) На строку) также не забудьте повторно разложить делитель. то есть в моем случае:

lines = height / (int)(16 * (dpix / 96))
person Rob    schedule 17.10.2014