【问题标题】:Autofit WinForms RichTextBox to its contents自动调整 WinForms RichTextBox 的内容
【发布时间】:2010-10-18 12:39:54
【问题描述】:

有人知道如何根据内容动态调整 RichTextBox 控件的大小吗?

【问题讨论】:

    标签: winforms richtextbox autosize


    【解决方案1】:

    这有点痛苦——使用 C# RichTextBox 经常令人沮丧。您是否尝试将框的大小调整到足以容纳其内容而无需任何滚动条?

    如果 RichTextBox 有固定字体,可以使用 TextRenderer.MeasureText 简单测量所需大小,并将框的宽度作为约束传入。

    ContentsResized 事件给你一个 ContentsResizedEventsArgs,它给你一个 NewRectangle,告诉你文本区域有多大。但它仅在文本更改时触发,如果您只是想测量现有的丰富文本框,这将没有那么有用(尽管您可能只是做一些 hacky,例如将框的文本设置为自身,触发此事件)。

    还有一堆Win32 api调用,比如使用EM_GETLINECOUNT(http://ryanfarley.com/blog/archive/2004/04/07/511.aspx)等

    【讨论】:

      【解决方案2】:

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

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

      [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...

      【讨论】:

        【解决方案3】:

        一个非常便宜的解决方案(一个可能充满问题的解决方案)是同时使用相同字体和大小的文本填充自动调整标签,然后只需将标签的宽度复制到 RTB 的宽度。

        所以,像这样:

        RichTextBox rtb = new RichTextBox();
        rtb.Text = "this is some text";
        rtb.Font = new Font("Franklin Gothic Medium Cond", 10, FontStyle.Regular);
        
        Label fittingLabel = new Label();
        fittingLabel.Text = rtb.Text;
        fittingLabel.Font = rtb.Font;
        fittingLabel.AutoSize = true;
        
        //Not sure if it's necessary to add the label to the form for it to autosize...
        fittingLabel.Location = new Point(-1000,-1000);
        this.Controls.Add(fittingLabel);
        
        rtb.Width = fittingLabel.Width;
        
        this.Controls.Remove(fittingLabel);
        

        【讨论】:

          【解决方案4】:

          再次假设一个固定的字体,你可以这样做:

          using (Graphics g = CreateGraphics())
          {
              richTextBox.Height = (int)g.MeasureString(richTextBox.Text,
                  richTextBox.Font, richTextBox.Width).Height;
          }
          

          【讨论】:

          • 只有在没有其他格式的情况下只使用一种(默认)字体时才有效,在这种情况下,我一开始就不会使用 RichTextBox。
          • @LouisSomers:使用 RichTexBox 不仅是因为它的格式化功能,还因为它能够撤消/重做操作。所以确实有很多实际情况下,RichTextBox 与常量格式一起使用。
          【解决方案5】:

          我想我来得太晚了,但看看this

          只有两行代码:

          private void rtb_ContentsResized(object sender, ContentsResizedEventArgs e)
          {
              ((RichTextBox)sender).Height = e.NewRectangle.Height + 5;
          }
          

          【讨论】:

          • 这正是我所需要的。请注意,wordwrap 必须 = true
          【解决方案6】:

          如this answer中所述,使用GetPreferredSize 要容易得多。那么你就不需要等待 ContentsResized 事件了。

          【讨论】:

          • 我刚刚测试过这个,不幸的是GetPerferredSize返回的高度太小了。您能否编辑答案并提供一些源代码,也许我遗漏了一些要点......
          • @sɐunıɔןɐqɐp:我的代码似乎也使用了 ContentsResized 事件中的 e.NewRectangle.Size,并指出 GetPreferredSize() 返回的大小有时返回的高度太小。很抱歉让您寄予厚望。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-13
          • 1970-01-01
          • 2012-09-26
          • 1970-01-01
          • 2011-01-22
          • 2011-03-22
          相关资源
          最近更新 更多