Adjust WPF RichTextBox width and height to match the width of the font

I am trying to install WPF RichTextBox to precisely place a character grid in a specific monospace font. I am currently using FormattedText to determine the width and height of my RichTextBox, but the dimensions it gives me are too small - in particular, the two characters in width are too small.

Is there a better way to accomplish this task? This is not like sizing 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; 
+4
source share
2 answers

Assuming you have a very simple RichTextBox with a standard FlowDocument inside it, then you need to consider all the additional RichTextBox layouts.

By default, the Document.PagePadding property is {5,0,5,0} . Therefore, you will need to add 10 to the width.

In addition, RichTextBox has BorderThickness , which is {1, 1, 1, 1} by default. Therefore, you will need to add 2 to the width.

So, the code you want might look like this:

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

If you do this, you will still be left at 1 character, but this is a bit misleading. RichTextBox will complete even if the text is just a tiny bit, and not the width of the entire character. If you add 2 to the width, this will work. I can’t determine exactly where these additional 2s come from. I have never tried to achieve such accuracy. I used to run into PagePadding and BorderThickness , but I just can't find the extra 2. It might just be the constant you're stuck with, but I doubt it. It has to be somewhere.

A little tip on creating a StandardizationLine you can do

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

to clear the cycle.

+5
source

I found a solution for problems with a lot of text fields. I changed it for general use.

Create the following structures 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 the following private variables in your class for the form (where you ever need to calculate the height of the text)

 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 the following method to your class for the 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 the above method to work according to your requirement ... Be sure to send the Rtf string as a parameter for the non-standard text of the method, and also remember to assign the available width and height for the Richtextbox variable in the method ...

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

-1
source

Source: https://habr.com/ru/post/1305885/


All Articles