2009-04-09 11 views

risposta

2

È una specie di problema: il C# RichTextBox è spesso frustrante con cui lavorare. Stai cercando di dimensionare la scatola abbastanza grande da contenere il suo contenuto senza alcuna barra di scorrimento?

Se il RichTextBox ha un carattere costante, è possibile utilizzare TextRenderer.MeasureText per misurare semplicemente la dimensione richiesta e passare la larghezza della casella come vincolo.

L'evento ContentsResized offre un oggetto ContentsResizedEventsArgs, che fornisce un NewRectangle che indica quanto è grande l'area di testo. Ma si attiva solo quando il testo cambia, il che non è così utile se si vuole semplicemente misurare un richtextbox esistente (anche se probabilmente si può semplicemente fare qualcosa di hacky come impostare il testo della casella su se stesso, innescando questo evento).

ci sono anche un sacco di chiamate API Win32, come l'utilizzo di EM_GETLINECOUNT (http://ryanfarley.com/blog/archive/2004/04/07/511.aspx), ecc

+0

evento ContentsResized come trucco funziona davvero, grazie – Nigrimmist

0

ho trovato una soluzione per i problemi di altezza casella di testo RTF .. ho modificato una per uso generale ..

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

Creare seguenti variabili private nella classe per la forma (dove mai è necessario calcolare rich text altezza)

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 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 Rtf stringa come parametro per il metodo non normale testo e anche assicurarsi di assegnare larghezza e altezza disponibili alla variabile Richtextbox nel metodo ...

È possibile giocare con WordWrap in base alle proprie esigenze ..

1

Una soluzione davvero economica (che è potenzialmente piena di problemi) consiste nel riempire simultaneamente un'etichetta di autofit con testo utilizzando lo stesso carattere e le stesse dimensioni, quindi basta copiare la larghezza dell'etichetta per la larghezza dell'RTB.

Quindi, in questo modo:

RichTextBox rtb = new RichTextBox(); 
rtb.Text = "this is some text"; 
rtb.Font = new Font("Franklin Gothic Medium Cond", 10, FontStyle.Regular); 

Label fittingLabel = new Label(); 
fittingLabel.Text = rtb.Text; 
fittingLabel.Font = rtb.Font; 
fittingLabel.AutoSize = true; 

//Not sure if it's necessary to add the label to the form for it to autosize... 
fittingLabel.Location = new Point(-1000,-1000); 
this.Controls.Add(fittingLabel); 

rtb.Width = fittingLabel.Width; 

this.Controls.Remove(fittingLabel); 
+0

C'è sicuramente una soluzione migliore allora questo. Questo è un vero e proprio hack – thecoshman

+0

Ha Ha. Funziona ... –

6

Anche in questo caso assumendo un carattere fisso hai potuto fare qualcosa di simile:

using (Graphics g = CreateGraphics()) 
{ 
    richTextBox.Height = (int)g.MeasureString(richTextBox.Text, 
     richTextBox.Font, richTextBox.Width).Height; 
} 
+1

Affinché il testo si adatti correttamente è necessario un +10. Almeno, quello ha funzionato per me. –

5

Credo che io sono troppo tardi, ma dare un'occhiata a this

Sono solo due righe di codice:

private void rtb_ContentsResized(object sender, ContentsResizedEventArgs e) 
{ 
    (RichTextBox)sender.Height = e.NewRectangle.Height + 5; 
} 
+0

Questo ha fatto esattamente quello di cui avevo bisogno. Nota che 'wordwrap' deve =' true' – gunfulker

0

È molto più semplice da utilizzare GetPreferredSize, come descritto in questa risposta. Quindi non è necessario attendere un evento ContentResized.

1

vedono questo link

basta usare ContentsResized evento stesso questo:

private void rtb_ContentsResized(object sender, ContentsResizedEventArgs e) 
{ 
     ((RichTextBox)sender).Height = e.NewRectangle.Height + 5; 
} 
Problemi correlati