WinForms FAQ - RichTextBox

Find answers for the most frequently asked questions
Expand All Collapse All

If you visit the selection a character at the time, you can get the current FontStyle and modify it directly to add or remove a style like Bold or Italic. Doing it a character at a time will avoid losing the other styles that are set. The problem with doing it a whole selection at a time is that the FontStyle of the entire selection is the common styles set among all characters in the selection. So, if one char is bold and one is not, then bold is not set when you retrieve the fontstyle for the entire selection. Doing things a character at the time, avoids this problem and allows things to work OK. You can download a working sample(CS,VB).

private void AddFontStyle(FontStyle style)
{
  int start = richTextBox1.SelectionStart;
  int len = richTextBox1.SelectionLength;
  System.Drawing.Font currentFont;
  FontStyle fs;
  for(int i = 0; i < len; ++i)
  {
    richTextBox1.Select(start + i, 1);
    currentFont = richTextBox1.SelectionFont;
    fs = currentFont.Style;
    //add style
    fs = fs | style;
    richTextBox1.SelectionFont = new Font(
      currentFont.FontFamily, 
      currentFont.Size, 
      fs
      );
  }
}

private void RemoveFontStyle(FontStyle style)
{
  int start = richTextBox1.SelectionStart;
  int len = richTextBox1.SelectionLength;
  System.Drawing.Font currentFont;
  FontStyle fs;
  for(int i = 0; i < len; ++i)
  {
    richTextBox1.Select(start + i, 1);
    currentFont = richTextBox1.SelectionFont;
    fs = currentFont.Style;
    //remove style
    fs = fs & ~style;
    richTextBox1.SelectionFont = new Font(
      currentFont.FontFamily, 
      currentFont.Size, 
      fs
      );
  }
}

private void button1_Click(object sender, System.EventArgs e)
{
  AddFontStyle(FontStyle.Bold);
}

Here is a suggestion from Nicholas Clark on how to avoid seeing the character by character changes appear as you apply the styles one character at a time in the above code. Create a hidden RTB and store the selected text in it. Then apply the attributes and copy it back into the original richtextbox, so that you don’t see the selection changing.


            private void change_font(FontStyle style,bool add) 
            {
                  richTextBox2.Rtf = richTextBox1.SelectedRtf;
                  int lengt = richTextBox2.Text.Length;
                  int length = richTextBox1.SelectionLength;
                  int start = richTextBox1.SelectionStart;
                  for (int i = 0; i < lengt; i++) {
                        richTextBox2.Select(i,1);
                        Font cfont = richTextBox2.SelectionFont;
                        FontStyle fs = cfont.Style;
                        if (add) {
                              fs = fs | style;
                        }
                        else {
                              fs = fs & ~style;
                        }
                        richTextBox2.SelectionFont = new Font(
                              cfont.FontFamily,
                              cfont.Size,
                              fs
                              );
                  }
                  richTextBox2.Select(0,richTextBox2.Text.Length);
                  richTextBox1.SelectedRtf = richTextBox2.SelectedRtf;
                  richTextBox1.Select(start,length);
                  this.richTextBox1.Focus();
                  isChanged = true;
            }
Permalink

One way to do this is to use the RichTextBox.SaveFile method.


private void button1_Click(object sender, System.EventArgs e)
{
    // Create a SaveFileDialog & initialize the RTF extension 
    SaveFileDialog saveFile1 = new SaveFileDialog();
    saveFile1.DefaultExt = '*.rtf';
    saveFile1.Filter = 'RTF Files|*.rtf';

    // get a file name from the user 
    if (saveFile1.ShowDialog() == DialogResult.OK)
    {
        // Save the RTF contents of the RichTextBox control that 
        // was dragged onto the Window Form and populated somehow 
        richTextBox1.SaveFile(saveFile1.FileName,
            RichTextBoxStreamType.RichText); //use to save RTF tags in file 
        //RichTextBoxStreamType.PlainText);//use to save plain text in file 
    }
}
Permalink

To add a hyperlink to the RichTextBox, so that it opens up the link you click on, ensure that DetectUrls property is set to True and call:


[C#]
private void richTextBox1_LinkClicked(object sender, System.Windows.Forms.LinkClickedEventArgs e)
{
    System.Diagnostics.Process.Start(e.LinkText);
}

[VB.NET]
Private  Sub richTextBox1_LinkClicked(ByVal sender As Object, ByVal e As System.Windows.Forms.LinkClickedEventArgs)
    System.Diagnostics.Process.Start(e.LinkText)
End Sub
Permalink

There is no direct support for printing rich text in the .NET Framework. To print it, you can use interop with the SendMessage API and these three messages to do your printing.

EM_SETTARGETDEVICE : specify the target device

EM_FORMATRANGE : format part of a rich edit control’s contents for a specific device

EM_DISPLAYBAND : send the output to the device

Here is a link to a MSDN article by Martin Muller that implements this interop solution.
Getting WYSIWYG Print Results from a .NET RichTextBox

Permalink

There are a couple different methods that can be used here. The first changes focus, so may not be possible if you have controls that fire validation. The second uses interop, which requires full trust.

Method 1:
Eric Terrell suggested this solution in an email to winformsfaq@syncfusion.com.

The richtextbox control contains a Lines array property, one entry for every line. Each line entry has a Length property. With this information, you can position the selection cursor using code such as:

	private void GoToLineAndColumn(RichTextBox RTB, int Line, int Column)
	{
		int offset = 0;
		for (int i = 0; i < Line - 1 && i < RTB.Lines.Length; i++)
		{
			offset += RTB.Lines[i].Length + 1;
		}
		RTB.Focus();
		RTB.Select(offset + Column, 0);
	}

(Note: you may want to store this.ActiveControl to be retrieved after calling Select()).

Method 2:


	const int SB_VERT = 1;
	const int EM_SETSCROLLPOS = 0x0400 + 222;

	[DllImport('user32', CharSet=CharSet.Auto)]
	public static extern bool GetScrollRange(IntPtr hWnd, int nBar, out int lpMinPos, out int lpMaxPos);

	[DllImport('user32', CharSet=CharSet.Auto)]
	public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, POINT lParam);

	[StructLayout(LayoutKind.Sequential)]
	public class POINT 
	{
		public int x;
		public int y;

		public POINT() 
		{
		}

		public POINT(int x, int y) 
		{
			this.x = x;
			this.y = y;
		}
	}

	// Example -- scroll the RTB so the bottom of the text is always visible.
	int min, max;
	GetScrollRange(richTextBox1.Handle, SB_VERT, out min, out max);
	SendMessage(richTextBox1.Handle, EM_SETSCROLLPOS, 0, new POINT(0, max - richTextBox1.Height));
Permalink

You use the SelectionFont and SelectionColor properties. Make sure the control had focus. Then the following code will set the currently selected text to a red-bold-courier font. If no text is currently selected, then any new text typed (or inserted) will be red-bold-courier.

[C#]
	richTextBox1.Focus();
	richTextBox1.SelectionColor = Color.Red;
	richTextBox1.SelectionFont = new Font ('Courier', 10, FontStyle.Bold);
[VB.NET]
	richTextBox1.Focus()
	richTextBox1.SelectionColor = Color.Red
	richTextBox1.SelectionFont = new Font ('Courier', 10, FontStyle.Bold)
Permalink

1) Set the AllowDrop property to true
2) Add handlers for both the DragEnter and DragDrop event

	this.richTextBox1.DragEnter += new System.Windows.Forms.DragEventHandler(this.richTextBox1_DragEnter);
	this.richTextBox1.DragDrop += new System.Windows.Forms.DragEventHandler(this.richTextBox1_DragEnter);

	....

	private void richTextBox1_DragEnter(object sender, 
			System.Windows.Forms.DragEventArgs e)
	{
		if (((DragEventArgs)e).Data.GetDataPresent(DataFormats.Text)) 
			((DragEventArgs)e).Effect = DragDropEffects.Copy;
		else
			((DragEventArgs)e).Effect = DragDropEffects.None;
	}

	private void richTextBox1_DragDrop(object sender, DragEventArgs e) 
	{
		// Loads the file into the control. 
		richTextBox1.LoadFile((String)e.Data.GetData('Text'), System.Windows.Forms.RichTextBoxStreamType.RichText);
	}

Here are VB snippets.

	    AddHandler Me.richTextBox1.DragEnter, New System.Windows.Forms.DragEventHandler(AddressOf Me.richTextBox1_DragEnter)
	 AddHandler Me.richTextBox1.DragDrop, New System.Windows.Forms.DragEventHandler(AddressOf Me.richTextBox1_DragEnter)

	.....


	Private Sub richTextBox1_DragEnter(sender As Object, e As System.Windows.Forms.DragEventArgs)
 
		If CType(e, DragEventArgs).Data.GetDataPresent(DataFormats.Text) Then
  			CType(e, DragEventArgs).Effect = DragDropEffects.Copy
		Else
			CType(e, DragEventArgs).Effect = DragDropEffects.None
		End If 

	End Sub ’richTextBox1_DragEnter


	Private Sub richTextBox1_DragDrop(sender As Object, e As DragEventArgs)

		’ Loads the file into the control. 
   		richTextBox1.LoadFile(CType(e.Data.GetData('Text'), [String]), System.Windows.Forms.RichTextBoxStreamType.RichText)

	End Sub ’richTextBox1_DragDrop 
Permalink

You use the LoadFile method of the RichTextBox, passing it a streamreader based on the resource. So include your RTF file as an embedded resource in your project, say RTFText.rtf. Then load your richtextbox with code such as

	Stream stream = this.GetType().Assembly.GetManifestResourceStream('MyNameSpace.RTFText.rtf');
	if (stream != null)
	{
 		StreamReader sr = new StreamReader(stream);
 		richTextBox1.LoadFile(stream, RichTextBoxStreamType.RichText);
 		sr.Close();
	}

Here is a VB snippet. Depending on your default namespace settings, you may not need explicit reference to the namespace in the GetManifestResourceStream argument.

	Dim stream As Stream = Me.GetType().Assembly.GetManifestResourceStream('MyNameSpace.RTFText.rtf')
	If Not (stream Is Nothing) Then
   		Dim sr As New StreamReader(stream)
   		richTextBox1.LoadFile(stream, RichTextBoxStreamType.RichText)
   		sr.Close()
	End If
Permalink

Share with

Couldn't find the FAQs you're looking for?

Please submit your question and answer.