2010-04-02 8 views
4

J'essaie de placer un fichier RichTextBox WPF afin de contenir exactement une grille de caractères dans une police monospace particulière. J'utilise actuellement FormattedText pour déterminer la largeur et la hauteur de mon RichTextBox, mais les mesures qu'il me fournit sont trop petites - en particulier deux caractères de largeur trop petite.Définition de la largeur et de la hauteur de la RichTextBox de WPF en fonction de la taille d'une police monospace

Existe-t-il une meilleure façon d'effectuer cette tâche? Cela ne semble pas être un moyen approprié pour 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; 
+0

Comment écrivez-vous le texte à la 'RichTextBox'? –

Répondre

5

En supposant que vous avez un RichTextBox très basique avec juste la norme FlowDocument à l'intérieur alors vous devez prendre en compte l'ensemble de la disposition supplémentaire RichTextBox utilisations.

La propriété Document.PagePadding est définie par défaut sur {5,0,5,0}. Donc vous devrez ajouter 10 à la largeur.

En outre, le RichTextBox a un BorderThickness 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 s'enroulera même si le texte est juste un tout petit peu plus large que la largeur d'un caractère entier. Si vous ajoutez 2 à la largeur, cela fonctionne. Je n'arrive pas à comprendre exactement d'où vient ce 2 supplémentaire. Je n'ai jamais essayé d'obtenir une largeur aussi précise. J'ai déjà rencontré les problèmes PagePadding et BorderThickness, mais je n'arrive pas à trouver les 2 supplémentaires. C'est peut-être une constante avec laquelle vous êtes coincé, mais j'en doute. Ça doit être quelque part.

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

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

pour nettoyer la boucle.

+0

Merveilleuse réponse. Pour répondre à votre question précédente, j'écris à la RichTextBox en attrapant OnPreviewKeyDown et OnPreviewTextInput et en manipulant les chaînes dans Runs manuellement. – zope

+1

Il semble y avoir quelques problèmes avec double.NaN (Auto) avec cette réponse, mais je pense que les pages BorderThickness \ PagePadding expliquent comment faire face à cela. Je ne suis pas encore tout à fait sûr. – zope

+0

@oxeb - Où trouvez-vous le problème 'double.NaN'? Cela ne me surprend pas trop. J'ai testé ceci mais seulement sur un projet avec juste un 'RichTextBox' dans VS2010. Il est possible que certaines des valeurs par défaut soient différentes. J'aurais dû préciser que vous pourriez avoir besoin d'ajouter une vérification d'erreur. J'espère que ça aide. –

-1

je trouve 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 et pas normal assurez-vous également affecter la largeur et la hauteur disponibles à la variable RichTextbox dans la méthode ...

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