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

发布于 2024-08-28 01:44:42 字数 993 浏览 8 评论 0原文

我正在尝试调整 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;

I am trying to fit a WPF RichTextBox to exactly accommodate a grid of characters in a particular monospace font. 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.

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

拧巴小姐 2024-09-04 01:44:42

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

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

此外,RichTextBoxBorderThickness 默认为 {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);

来清理循环。

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.

The Document.PagePadding property defaults to {5,0,5,0}. So you will have to add 10 to the width.

Additionally the RichTextBox has a BorderThickness that defaults to {1, 1, 1, 1}. So you will have to add 2 to the width.

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. The RichTextBox will wrap even if the text is just a tiny bit to wide not just a whole character width. If you add 2 to the width it works out. I can't figure out exactly where that extra 2 is coming from. 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. It's got to be somewhere.

A small tip on producing the StandardizationLine you can do

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

to clean up the loop.

暖树树初阳… 2024-09-04 01:44:42

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

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

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

I found a solution for the Rich text box height issues.. i have modified it a for general use..

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

You can play with WordWrap depending on your requirement...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文