Modificando la larghezza e l'altezza WPF RichTextBox secondo la dimensione di un font monospace
-
24-09-2019 - |
Domanda
Sto cercando di adattare una WPF RichTextBox per accogliere esattamente una griglia di caratteri in un particolare tipo di carattere a spaziatura fissa. Attualmente sto usando FormattedText per determinare la larghezza e l'altezza del mio RichTextBox, ma le misure che sta fornendo me con sono troppo piccole -. In particolare due caratteri di larghezza troppo piccola
C'è un modo migliore per eseguire questa operazione? Questo non sembra essere un modo appropriato per determinare la dimensione del mio controllo.
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;
Soluzione
Supponendo di avere un RichTextBox
molto semplice con solo il FlowDocument
di serie al suo interno, allora si deve prendere in considerazione tutti gli usi in più di layout RichTextBox
.
Le impostazioni predefinite di proprietà Document.PagePadding
a {5,0,5,0}
. Così si dovrà aggiungere 10 alla larghezza.
Inoltre, la RichTextBox
ha un BorderThickness
che il default è {1, 1, 1, 1}
. Così si dovrà aggiungere 2 alla larghezza.
Quindi, il codice che si desidera potrebbe apparire come:
var pagePadding = rtb.Document.PagePadding;
var borderThickness = rtb.BorderThickness;
rtb.Width = formattedText.Width
+ pagePadding.Left + pagePadding.Right
+ borderThickness.Left + borderThickness.Right;
Se lo fai sarà comunque fuori da 1 carattere, ma questo è un po 'fuorviante. Il RichTextBox
avvolgerà anche se il testo è solo un pochino a largo non solo una larghezza di carattere generale. Se si aggiunge 2 alla larghezza va a finire. Io non riesco a capire esattamente dove quel qualcosa in più 2 proviene. Non ho mai cercato di ottenere la larghezza di essere così preciso. Ho eseguito in questioni PagePadding
e BorderThickness
prima, ma non riesco proprio a trovare il più 2. Potrebbe essere solo una costante si è bloccato con, ma ne dubito. Deve essere da qualche parte.
Una piccola punta sulla produzione del StandardizationLine
si può fare
string StandardizationLine = new string('X', columns);
per ripulire il ciclo.
Altri suggerimenti
Ho trovato una soluzione per i problemi di altezza casella di testo RTF .. ho modificato un per uso generale ..
Crea seguente struct nell'applicazione ....
[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 seguenti variabili private nella tua classe per modulo (dove mai è necessario calcolare ricca altezza del testo)
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);
Aggiungi seguente metodo alla classe per la 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;
}
Potrebbe essere necessario modificare il metodo di cui sopra per farla funzionare secondo il vostro requisito ... Assicurarsi di inviare stringa RTF come parametro per il metodo di testo non è normale e anche fare in modo di larghezza disponibile assegnare e l'altezza alla variabile RichTextBox nel metodo ...
Si può giocare con WordWrap a seconda della vostra esigenza ...