简体   繁体   English

根据等宽字体的大小设置WPF RichTextBox的宽度和高度

[英]Setting WPF RichTextBox width and height according to the size of a monospace font

I am trying to fit a WPF RichTextBox to exactly accommodate a grid of characters in a particular monospace font. 我正在尝试使用WPF RichTextBox来精确地容纳特定等宽字体中的字符网格。 I am currently using FormattedText to determine the width and height of my RichTextBox, but the measurements it is providing me with are too small--specifically two characters in width too small. 我目前正在使用FormattedText来确定我的RichTextBox的宽度和高度,但它为我提供的测量值太小 - 特别是两个宽度太小的字符。

Is there a better way to perform this task? 有没有更好的方法来执行此任务? This does not seem to be an appropriate way to determine the size of my control. 这似乎不是确定我的控件大小的合适方法。

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;

Assuming you have a very basic RichTextBox with just the standard FlowDocument inside it then you have to take into account all of the extra layout RichTextBox uses. 假设你有一个非常基本的RichTextBox ,里面只有标准的FlowDocument ,那么你必须考虑RichTextBox使用的所有额外布局。

The Document.PagePadding property defaults to {5,0,5,0} . Document.PagePadding属性默认为{5,0,5,0} So you will have to add 10 to the width. 所以你必须在宽度上加10。

Additionally the RichTextBox has a BorderThickness that defaults to {1, 1, 1, 1} . 此外, RichTextBoxBorderThickness默认为{1, 1, 1, 1} BorderThickness {1, 1, 1, 1} So you will have to add 2 to the width. 所以你必须在宽度上加2。

So the code you want could look like: 所以你想要的代码看起来像:

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

If you do that you will still be off by 1 character, but that's a bit misleading. 如果你这样做,你仍然会被1个字符关闭,但这有点误导。 The RichTextBox will wrap even if the text is just a tiny bit to wide not just a whole character width. 即使文本只是一个很小的宽度而不仅仅是整个字符宽度, RichTextBox也会换行。 If you add 2 to the width it works out. 如果你在宽度上添加2就可以了。 I can't figure out exactly where that extra 2 is coming from. 我无法确切知道额外的2来自哪里。 I've never tried to get the width to be so exact. 我从未试图让宽度如此精确。 I have run into the PagePadding and BorderThickness issues before, but I just can't find the extra 2. It might just be a constant you are stuck with, but I doubt it. 我之前遇到过PagePaddingBorderThickness问题,但是我找不到额外的2.它可能只是一个常数,你被困住了,但我怀疑它。 It's got to be somewhere. 它必须在某个地方。

A small tip on producing the StandardizationLine you can do 您可以做一个关于生产StandardizationLine小技巧

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

to clean up the loop. 清理循环。

I found a solution for the Rich text box height issues.. i have modified it a for general use.. 我找到了Rich文本框高度问题的解决方案..我已将其修改为一般用途..

Create following structs in your application.... 在您的应用程序中创建以下结构....

[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;
    }

Create following private variables in your class for form (where ever you need to calculate rich text height) 在类中为表单创建以下私有变量(您需要计算富文本高度)

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);

Add following method to your Class for form 将以下方法添加到表格的类中

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;
        }

You may need to modify above method to make it work as per your requirement... Make sure to send Rtf string as parameter to method not normal text and also make sure to assign available width and height to the Richtextbox variable in the method... 您可能需要修改上述方法以使其按照您的要求工作...确保将Rtf字符串作为参数发送到方法而不是普通文本,并确保将可用的宽度和高度分配给方法中的Richtextbox变量。 。

You can play with WordWrap depending on your requirement... 您可以根据您的要求使用WordWrap ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM