【问题标题】:Autoscaling RichTextBox自动缩放 RichTextBox
【发布时间】:2019-10-09 07:14:52
【问题描述】:

我正在尝试使用只读 RichTextBoxes 来显示用户生成的文本。文本框和控件的高度应取决于内容并限制在某个最大值,超过该点的任何内容都使用滚动条。

AutoSize 似乎不适用于 RTB

public void Rescale()
{
    Point pt = rtbComment.GetPositionFromCharIndex(rtbComment.Text.Length);
    int height = rtbComment.GetPositionFromCharIndex(rtbComment.Text.Length).Y + (int)rtbComment.SelectionFont.GetHeight();
    if (height > 250)
        height = 250;
    this.Size = new System.Drawing.Size(616, height + 50);
    rtbComment.Size = new System.Drawing.Size(614, height);
}

这对于短的 cmets 或带有少量文本和许多换行符的 cmets 非常有效,但对于分成 ~ 4 行的长单行,我从 GetPositionFromCharIndex 得到的点都是错误的 - 该函数将它放在 105px 的某个地方当它实际上接近 60 时,在 y 轴上向下,使文本框大约是预期大小的两倍。

这里的宽度似乎不是问题,因为该框以我设置的宽度开始并再次读取该点会产生相同的结果。

【问题讨论】:

  • 在实际尝试渲染之前,您无法知道在特定页面上渲染时文本块的大小。 RTF 可以有不同的字体、大小、由连字符控制的换行等。您所说的换行符实际上可能是 段落,与换行生成的行有不同的间距
  • @PanagiotisKanavos 它什么时候尝试渲染呢?我指的是字符串中的实际换行符 (\n)
  • RTF(格式)没有\n和RichTextBox converts newline characters to /par instead of /line
  • 在任何情况下,您都无法从特定控件轻松控制 form 的 布局。典型的方法是使用停靠或像TableLayoutPanel 这样的布局面板,在面板/容器上指定自动调整大小和最大大小并将控件设置为填充其单元格
  • 您可以使用TextRenderer.MeasureText 来确定在特定大小的容器中呈现文本时的大小。如果宽度是固定的,提供一个特定宽度的容器(一个矩形),然后获取测量文本的高度并将其最小/最大到您预定义的最大高度。

标签: c# .net winforms richtextbox autosize


【解决方案1】:

解决了。

我使用了TextRenderer.MeasureText 方法。

由于此方法忽略了非常长的行将在 RichTextBox 中接收一个或多个自动换行符这一事实,我编写了一个函数,该函数通过换行符将文本手动拆分为任意长度的行,然后将这些行中的每一行测量为检查它将在 RTB 中使用多少行。

这是函数,以防万一有人需要:

public int getLines(string comment)
{
    int height_ln = 0;

    string[] lines;

    //split into lines based on linebreaks
    if (comment.Contains("\n"))
    {
        lines = comment.Split('\n');
    }
    else
    {
        lines = new string[1];
        lines[0] = comment;
    }

    //check each line to see if it'll receive automatic linebreaks
    foreach(string line in lines)
    {
        int text_width = TextRenderer.MeasureText(line, rtbKommentar.Font).Width;
        double text_lines_raw = (double)text_width / 1400; //1400 is the width of my RichTextBox

        int text_lines = 0;

        if (line.Contains("\r")) //Please don't call me out on this, I'm already feeling dirty
            text_lines = (int)Math.Floor(text_lines_raw);
        else
            text_lines = (int)Math.Ceiling(text_lines_raw);
        if (text_lines == 0)
            text_lines++;

        height_ln += text_lines;
    }
    return height_ln; //this is the number of lines required, to adjust the height of the RichTextBox I need to multiply it by 15, which is the font's height.
}

【讨论】:

  • TextRenderer 不会忽略所有换行符(强制或由自动换行确定)。不过,您需要指定正确的 TextFormat 标志。使用这些:var flags = TextFormatFlags.LeftAndRightPadding | TextFormatFlags.Top | TextFormatFlags.Left | TextFormatFlags.TextBoxControl | TextFormatFlags.WordBreak;。在TextRenderer.MeasureText() 中,使用允许IDeviceContextTextFormatFlags 参数的重载。 IDeviceContext 可以使用Control.CreateGraphics() 生成(之后处理Graphics 对象)。
  • 没有TextFormatFlags.WordBreak;,例如,它将测量文本,因为它是单行布局。您还需要指定容器的大小。使用new Size(Control.ClientSize.Width, MaxHeight) 作为这个参数。以这种方式测量时,TextRenderer 将返回指定容器边界内文本的正确大小。
【解决方案2】:

WinForm RichtextBox 公开了ContentsResized Event,当与MinimumSize PropertyMaximumSize Property 结合使用时,可以实现自动调整大小的控件。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        rtbComment.MinimumSize = new Size(250, 200);
        rtbComment.MaximumSize = new Size(250, 400);
        rtbComment.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.Vertical;
        rtbComment.ContentsResized += rtbComment_ContentResized;

    }

    private void rtbComment_ContentResized(object sender, ContentsResizedEventArgs e)
    {
        rtbComment.Size = e.NewRectangle.Size;
    }
}

【讨论】:

    猜你喜欢
    • 2019-11-07
    • 1970-01-01
    • 2019-02-24
    • 2019-08-16
    • 2018-12-13
    • 2015-05-09
    • 1970-01-01
    • 2017-02-18
    • 2014-11-16
    相关资源
    最近更新 更多