【发布时间】:2010-10-18 12:39:54
【问题描述】:
有人知道如何根据内容动态调整 RichTextBox 控件的大小吗?
【问题讨论】:
标签: winforms richtextbox autosize
有人知道如何根据内容动态调整 RichTextBox 控件的大小吗?
【问题讨论】:
标签: winforms richtextbox autosize
这有点痛苦——使用 C# RichTextBox 经常令人沮丧。您是否尝试将框的大小调整到足以容纳其内容而无需任何滚动条?
如果 RichTextBox 有固定字体,可以使用 TextRenderer.MeasureText 简单测量所需大小,并将框的宽度作为约束传入。
ContentsResized 事件给你一个 ContentsResizedEventsArgs,它给你一个 NewRectangle,告诉你文本区域有多大。但它仅在文本更改时触发,如果您只是想测量现有的丰富文本框,这将没有那么有用(尽管您可能只是做一些 hacky,例如将框的文本设置为自身,触发此事件)。
还有一堆Win32 api调用,比如使用EM_GETLINECOUNT(http://ryanfarley.com/blog/archive/2004/04/07/511.aspx)等
【讨论】:
我找到了富文本框高度问题的解决方案。我已将其修改为一般用途。
在您的应用程序中创建以下结构......
[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...
【讨论】:
一个非常便宜的解决方案(一个可能充满问题的解决方案)是同时使用相同字体和大小的文本填充自动调整标签,然后只需将标签的宽度复制到 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);
【讨论】:
再次假设一个固定的字体,你可以这样做:
using (Graphics g = CreateGraphics())
{
richTextBox.Height = (int)g.MeasureString(richTextBox.Text,
richTextBox.Font, richTextBox.Width).Height;
}
【讨论】:
我想我来得太晚了,但看看this
只有两行代码:
private void rtb_ContentsResized(object sender, ContentsResizedEventArgs e)
{
((RichTextBox)sender).Height = e.NewRectangle.Height + 5;
}
【讨论】:
wordwrap 必须 = true
如this answer中所述,使用GetPreferredSize 要容易得多。那么你就不需要等待 ContentsResized 事件了。
【讨论】: