[c#] RichTextBox RTF(rich text format) 기본적인 이용 방법

TextBox는 메모장이고 RichTextBox는 워드패드다. 문자열에 스타일을 적용하려면 RichTextBox를 써야 한다. RichTextBox는 윈도우즈 차원에서 제공되는 것이며 .네트는 win32 api를 랩wrap하여 지원한다. 그러나 완벽하지는 않아서 높은 수준으로 이용하려면 직접 win32 api를 제어해야 한다. 스타일이 적용된 것은 rich text format이라 하며 줄여서 rtf라고 한다. 스타일을 제어하는 데에는 크게 세 가지 방법이 있다.

문자열을 입력하기 전에 스타일을 설정하기

스타일을 설정하면 그 뒤로 추가되는 문자열에 자동으로 적용된다. 이렇게 하면 \n으로 줄을 바꾸거나 새로운 스타일을 적용하기 전까지 유지된다.

The text color setting applies until the property is changed to a different color or until the insertion point is moved to a different section within the control.
RichTextBox.SelectionColor Property

위 설명은 RichTextBox.SelectionColor에 한정되는 게 아니라 다른 스타일에도 일반적으로 적용된다. 문자열이 삽입되는 지점이 다른 섹션으로 바뀌면 스타일이 풀린다는 내용으로 줄이 바뀌어 문단이 달라지면 섹션이 바뀌는 거다. 그러나 여기에는 버그로 보이는 문제가 있는데 아래 예제들에서 1은 스타일이 해제되지만 2는 그렇지 않다. 물론 이들은 논리적으로 같다.

// 1
richTextBox1.SelectionFont = new(richTextBox1.Font, FontStyle.Bold);
            
richTextBox1.AppendText("abcde\n"); // bold
richTextBox1.AppendText("abcde"); // regular
// 2
richTextBox1.SelectionFont = new(richTextBox1.Font, FontStyle.Bold);
            
richTextBox1.AppendText("abcde\nabcde"); // all bold

TextBox의 경우에는 줄을 바꿀 때 \r\n으로 해야 하지만 RichTextBox의 경우에는 \n만으로도 된다. 문자열 추가는 AppendText로 하는데 이게 많이 느려서 이 방법은 좋지 않다.

범위를 정하여 일괄적으로 적용하기

문자열을 일단 출력한 뒤 커서의 위치를 정해 가며 스타일을 적용할 수 있다. 예를 들어 양수를 빨간 색으로 출력하는 경우 출력된 문자열을 파스하여 숫자를 추출한 뒤 정수 연산을 하고 커서의 위치를 정한 뒤 스타일을 설정해야 한다. 번거로워서 역시 좋지 않은 방법이다. 아래는 wpf 예제다.

TextRange TextRangeTest;

private void ToggleButton_Checked(object sender, RoutedEventArgs e)
{
    TextRangeTest = new TextRange(RichTextBoxTest.Selection.Start, RichTextBoxTest.Selection.End);
    TextRangeTest.Text = RichTextBoxTest.Selection.Text;
    TextRangeTest.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Red);
}

private void ToggleButton_Unchecked(object sender, RoutedEventArgs e)
{
    TextRangeTest = new TextRange(RichTextBoxTest.Selection.Start, RichTextBoxTest.Selection.End);
    TextRangeTest.Text = RichTextBoxTest.Selection.Text;
    TextRangeTest.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Black);
}

rtf로 코딩하기

어렵지만 정교하게 제어할 수 있고 빨라서 제일 좋은 방법이다. 딜리미터인 \를 이용하여 rtf 문법에 맞게 코딩하면 되는데 좀 복잡하다. StringBuilder에다 코딩을 하여 아래와 같이 RichTextBox.Rtf에 어싸인하면 빠르다. \ 뒤에 붙는 걸 컨트롤 워드라고 한다. 두 개 이상의 컨트롤 워드들은 붙여서 쓸 수 있고 출력할 문자열은 컨트롤 워드 뒤 한 칸을 띄우고 입력한다.

\colortbl은 color table로서 이용할 색을 조합하여 그 뒤에 나열한 뒤 번호로 불러서 쓴다.
\cf1은 foreground color로서 컬러 테이블의 첫 번째 색을 호출하여 글꼴에 적용한다. 0이 아닌 1부터 시작하는 거에 유의한다.
\par는 paragraph로서 줄을 바꿔 문단을 구분한다.
\cf0은 글꼴에 적용한 색을 초기화한다. 컨트롤 워드 뒤에 붙는 0은 초기화하는 거다.
\b는 bold로서 글꼴을 굵게 한다.

richTextBox1.Rtf = @"{\rtf abcde\par {\colortbl; \red255\green0\blue0;}\cf1 12345\par\cf0\b qwert\b0}"; // rgb 255, 0, 0 is red.