Réglage de la largeur et de la hauteur WPF RichTextBox selon la taille d'une police monospace

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

  •  24-09-2019
  •  | 
  •  

Question

Je suis en train d'installer un WPF RichTextBox pour accueillir exactement une grille de caractères dans une police particulière à espacement fixe. J'utilise actuellement FormattedText pour déterminer la largeur et la hauteur de mon RichTextBox, mais les mesures qu'il me Doter trop petits -. En particulier deux caractères de largeur trop petite

Y at-il une meilleure façon d'effectuer cette tâche? Cela ne semble pas être un bon moyen de déterminer la taille de mon contrôle.

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;
Était-ce utile?

La solution

En supposant que vous avez un RichTextBox très basique avec juste la norme FlowDocument à l'intérieur alors vous devez prendre en compte tous les RichTextBox supplémentaires de mise en page utilise.

Les valeurs par défaut de propriété de Document.PagePadding à {5,0,5,0}. Donc, vous devrez ajouter 10 à la largeur.

De plus, le RichTextBox a BorderThickness que par défaut {1, 1, 1, 1}. Donc, vous devrez ajouter 2 à la largeur.

Ainsi, le code que vous voulez pourrait ressembler à:

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

Si vous faites cela, vous serez toujours hors de 1 caractère, mais c'est un peu trompeur. Le RichTextBox envelopperez même si le texte est juste un tout petit peu à l'échelle non seulement une largeur de caractère entier. Si vous ajoutez 2 à la largeur, il fonctionne. Je ne peux pas comprendre exactement où que 2 supplémentaire vient. Je ne l'ai jamais essayé d'obtenir la largeur de l'être exact. J'ai couru dans les questions de PagePadding et BorderThickness avant, mais je ne peux pas trouver le 2. supplémentaire Il pourrait juste être un vous êtes coincé avec, mais je doute constant il. Il faut que ce soit quelque part.

Une petite astuce sur la production du StandardizationLine que vous pouvez faire

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

pour nettoyer la boucle.

Autres conseils

J'ai trouvé une solution pour les problèmes de hauteur de texte enrichi .. Je l'ai modifié un pour un usage général ..

Créer dans votre struct suivant l'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;
    }

Créer des variables privées suivantes dans votre classe pour la forme (où que vous devez calculer la hauteur de texte riche)

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

Ajouter méthode suivante à votre classe pour la forme

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

Vous devrez peut-être modifier méthode ci-dessus pour le faire fonctionner selon vos besoins ... Assurez-vous d'envoyer la chaîne Rtf en tant que paramètre à la méthode du texte pas normal et assurez-vous d'attribuer la largeur et la hauteur disponibles à la variable RichTextbox dans la méthode ...

Vous pouvez jouer avec WordWrap en fonction de vos besoins ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top