I'm on your side, when times get rough.

2011-09-06

[C# WinForm] Height of RTF content in RichTextBox. #1

Filed under: Programming — Peter_KIM @ 09:56

RTF 텍스트는 다양한 글꼴의 형식으로 표시되므로, 전체 텍스트를 표시하는 각각의 문자에 대한 높이와 간격 등의 값을 구하여, 텍스트의 높이를 구하는 것이, 정석일 듯합니다.

여러 가지 방법이 있겠지만, RTF 텍스트의 전체 높이를 계산하는 방법 중의 한가지는 RichTextBox 컨트롤의 세로 스크롤 바를 이용하는 것입니다.

TextBox, ListBox, ListView 컨트롤과 같이 다양한 컨트롤에 스크롤 바가 포함되어 있습니다. 이런 컨트롤의 스크롤 바를 제어할 있는 Win32 API 함수가 존재합니다. 언젠가 이야기 했지만, 대부분의 .NET 기본 컨트롤 역시 Win32 컨트롤에 대한 확장일 뿐이므로, 다음과 같은 Win32 API 함수를 호출하여 적용할 있습니다.

GetScrollBarInfo(), GetScrollInfo(), GetScrollPos(), GetScrollRange(), SetScrollInfo(), SetScrollPos(), SetScrollRange()

외에도 Win32 스크롤과 관련된 메시지를 전달하는 것도 가능합니다.

RTF 텍스트 높이를 계산하는 데에는 GetScrollBarInfo(), GetScrollRange() 함수를 사용합니다.

우선 WinForm 프로젝트를 생성하고 아래의 그림과 같이 버튼과 RichTextBox 컨트롤을 배치합니다.

clip_image001[3]

RichTextBox 컨트롤의 BoarderStyle, ScrollBars 속성을 None 값으로 설정합니다.

private UInt32 SB_VERT = 1;

private UInt32 OBJID_VSCROLL = 0xFFFFFFFB;

 

[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;

}

 

[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);

WinForm 클래스의SizeChanged 이벤트 함수를 아래와 같이 구현합니다.

private void Form1_SizeChanged(object sender, EventArgs e)

{

    this.richTextBox1.Width = this.ClientSize.Width;

}

버튼의 Click 이벤트를 아래와 같이 구현합니다.

private void button1_Click(object sender, EventArgs e)

{

    int nHeight = 0;

    int nMin = 0, nMax = 0;

 

    SCROLLBARINFO psbi = new SCROLLBARINFO();

    psbi.cbSize = Marshal.SizeOf(psbi);

 

    this.richTextBox1.Height = 10;

    this.richTextBox1.ScrollBars = RichTextBoxScrollBars.Vertical;

 

    int nResult = GetScrollBarInfo(this.richTextBox1.Handle, OBJID_VSCROLL, ref psbi);

    if (psbi.rgstate[0] == 0)

    {

        GetScrollRange(this.richTextBox1.Handle, SB_VERT, out nMin, out nMax);

 

        nHeight = (nMax – nMin);

        this.richTextBox1.Height = nHeight;

    }

    this.richTextBox1.ScrollBars = RichTextBoxScrollBars.None;

}

우선, RichTextBox 컨트롤에서 세로 스크롤 바가 표시될 있도록 크기를 대략 10Pixel 정도로 조정하고, Scrollbars 속성을 설정합니다. 이후, API 함수를 호출하여, 스크롤 영역의 최소, 최대 값을 구하여, 차이를 RichTextBox 컨트롤의 높이로 설정합니다.

전체 소스 코드는 아래의 주소에서 내려 받을 있습니다.

https://skydrive.live.com/embedicon.aspx/.Public/RichTextBoxHeight.7z?cid=1bbcdfedee1c617e&sc=documents

Create a free website or blog at WordPress.com.