【问题标题】:Setting WPF RichTextBox width and height according to the size of a monospace font根据等宽字体的大小设置 WPF RichTextBox 的宽度和高度
【发布时间】:2010-04-02 21:02:00
【问题描述】:

我正在尝试调整 WPF RichTextBox 以完全适应特定等宽字体中的字符网格。我目前正在使用 FormattedText 来确定我的 RichTextBox 的宽度和高度,但是它为我提供的测量值太小了——特别是两个字符的宽度太小了。

有没有更好的方法来执行这项任务?这似乎不是确定控件大小的合适方法。

RichTextBox rtb;
rtb = new RichTextBox();
FontFamily fontFamily = new FontFamily("Consolas");
double fontSize = 16;
char standardizationCharacter = 'X';
String standardizationLine = "";
for(long loop = 0; loop < columns; loop ++) {
    standardizationLine += standardizationCharacter;
}
standardizationLine += Environment.NewLine;
String standardizationString = "";
for(long loop = 0; loop < rows; loop ++) {
    standardizationString += standardizationLine;
}
Typeface typeface = new Typeface(fontFamily, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal);
FormattedText formattedText = new FormattedText(standardizationString, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, fontSize, Brushes.Black);
rtb.Width = formattedText.Width;
rtb.Height = formattedText.Height;

【问题讨论】:

  • 您如何将文本写入RichTextBox

标签: c# wpf richtextbox monospace


【解决方案1】:

假设您有一个非常基本的RichTextBox,其中只有标准FlowDocument,那么您必须考虑RichTextBox 使用的所有额外布局。

Document.PagePadding 属性默认为 {5,0,5,0}。所以你必须在宽度上加 10。

另外RichTextBox 有一个BorderThickness,默认为{1, 1, 1, 1}。所以你必须在宽度上加 2。

所以你想要的代码可能是这样的:

var pagePadding = rtb.Document.PagePadding;
var borderThickness = rtb.BorderThickness;
rtb.Width = formattedText.Width
    + pagePadding.Left + pagePadding.Right 
    + borderThickness.Left + borderThickness.Right;

如果你这样做,你仍然会偏离 1 个字符,但这有点误导。 RichTextBox 将换行,即使文本只是稍微宽一点,而不仅仅是整个字符宽度。如果你在宽度上加上 2 就可以了。我无法弄清楚额外 2 的确切来源。我从来没有试图让宽度如此精确。我之前遇到过PagePaddingBorderThickness 问题,但我找不到额外的2。它可能只是你坚持的常数,但我对此表示怀疑。它一定在某个地方。

一个关于制作StandardizationLine的小技巧你可以做

string StandardizationLine = new string('X', columns);

清理循环。

【讨论】:

  • 精彩的答案。为了回答您之前的问题,我通过捕获 OnPreviewKeyDown 和 OnPreviewTextInput 并手动操作 Runs 中的字符串来写信给 RichTextBox。
  • 这个答案似乎与 double.NaN (Auto) 存在一些问题,但我认为 BorderThickness \ PagePadding 页面解释了如何处理这个问题。我还不太确定。
  • @oxeb - 你从哪里得到double.NaN 的问题?这并没有让我太惊讶。我确实对此进行了测试,但仅在 VS2010 中只有一个简单的 RichTextBox 的项目上进行了测试。某些默认值可能不同。我应该说您可能需要添加错误检查。希望对您有所帮助。
  • 它有帮助!我使用这种技术的宽度组合来完成所有工作,并让它自行调整高度,AUTO 调整高度,然后基本上通过回调执行 Height = ActualHeight 来冻结它。
【解决方案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...

【讨论】:

    猜你喜欢
    • 2015-05-21
    • 1970-01-01
    • 2012-12-25
    • 1970-01-01
    • 1970-01-01
    • 2013-09-02
    • 2016-01-17
    • 2010-09-25
    • 2021-02-13
    相关资源
    最近更新 更多