Establecimiento del ancho de WPF RichTextBox y altura de acuerdo con el tamaño de una fuente de espacio sencillo

StackOverflow https://stackoverflow.com/questions/2569191

  •  24-09-2019
  •  | 
  •  

Pregunta

Estoy intentando adaptarse a una WPF RichTextBox para acomodar exactamente una cuadrícula de caracteres en una fuente de espacio sencillo en particular. Actualmente estoy usando FormattedText para determinar el ancho y la altura de mi RichTextBox, pero las medidas que me está proporcionando son demasiado pequeños -. específicamente dos caracteres de ancho demasiado pequeño

¿Hay una mejor manera de realizar esta tarea? Esto no parece ser una forma adecuada para determinar el tamaño de mi 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;
¿Fue útil?

Solución

Asumiendo que tiene un RichTextBox muy básico con sólo el FlowDocument estándar dentro de ella entonces usted tiene que tener en cuenta todos los usos adicionales de diseño RichTextBox.

Los valores por defecto de propiedad Document.PagePadding a {5,0,5,0}. Por lo que tendrá que añadir 10 a la anchura.

Además, el RichTextBox tiene una BorderThickness que por defecto es {1, 1, 1, 1}. Por lo que tendrá que añadir 2 a la anchura.

Así que el código que desea podría ser:

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

Si lo hace, usted seguirá siendo fuera por 1 carácter, pero eso es un poco engañoso. El RichTextBox se ajustará incluso si el texto es sólo un poquito a la amplia no sólo un ancho de carácter general. Si se agrega 2 a la anchura funciona. No puedo averiguar exactamente donde ese extra 2 está viniendo. Nunca he tratado de conseguir el ancho a ser tan exacta. Me he encontrado con los problemas PagePadding y BorderThickness antes, pero simplemente no puedo encontrar el extra 2. puede que solo sea una constante que hay que contentarse con, pero lo dudo. Tiene que estar en alguna parte.

Una pequeña punta en la producción de la StandardizationLine se puede hacer

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

para limpiar el bucle.

Otros consejos

He encontrado una solución para los problemas de altura de la caja de texto enriquecido .. lo he modificado un para uso general ..

Crea siguientes estructuras en su solicitud ....

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

Crear siguientes variables privadas en su clase para la forma (donde quiera que precisa para calcular la altura de texto enriquecido)

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

Añadir siguiente método a la clase de forma

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

Es posible que tenga que modificar el método anterior para hacer que funcione según sus necesidades ... Asegúrese de enviar cadena RTF como parámetro al método de texto no es normal y también asegurarse de anchura disponible de asignación y la altura a la variable RichTextbox en el método ...

Se puede jugar con WordWrap función de sus necesidades ...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top