c# RichTextBox 줄 간격 설정하기

좀 복잡하다. RichTextBox는 윈도우즈 차원에서 제공되는 컨트롤인데 델파이와 달리 .네트는 win32 api를 제대로 랩wrap하지 않아서 아래와 같이 win32 api를 직접 제어해야 한다.

[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, PARAFORMAT2 lParam);

[StructLayout(LayoutKind.Sequential)]
public struct PARAFORMAT2
{
    public int cbSize;
    public uint dwMask;
    public Int16 wNumbering;
    public Int16 wReserved;
    public int dxStartIndent;
    public int dxRightIndent;
    public int dxOffset;
    public Int16 wAlignment;
    public Int16 cTabCount;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public int[] rgxTabs;
    public int dySpaceBefore;
    public int dySpaceAfter;
    public int dyLineSpacing;
    public Int16 sStyle;
    public byte bLineSpacingRule;
    public byte bOutlineLevel;
    public Int16 wShadingWeight;
    public Int16 wShadingStyle;
    public Int16 wNumberingStart;
    public Int16 wNumberingStyle;
    public Int16 wNumberingTab;
    public Int16 wBorderSpace;
    public Int16 wBorderWidth;
    public Int16 wBorders;
}

const int WM_USER = 0x0400;
const int PFM_LINESPACING = 0x00000100; // richedit.h in windows sdk
const int EM_SETPARAFORMAT = WM_USER + 71;
const int SCF_ALL = 0x0004; // for all text regardless of selection

private void Form1_Click(object sender, EventArgs e)
{
    PARAFORMAT2 paraFormat2 = new();

    paraFormat2.cbSize = Marshal.SizeOf(paraFormat2);
    paraFormat2.dwMask = PFM_LINESPACING;
    paraFormat2.bLineSpacingRule = 4; // twips less than 1 line space
    paraFormat2.dyLineSpacing = 200; // no line space

    SendMessage(richTextBox1.Handle, EM_SETPARAFORMAT, SCF_ALL, raraFormat2);
}

SendMessage의 아규먼트로는 아래와 같이 IntPtr을 넣는 게 원칙이긴 한데 조금 더 복잡하다.

[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);

private void Form1_Click(object sender, EventArgs e)
{
    PARAFORMAT2 paraFormat2 = new();

    paraFormat2.cbSize = Marshal.SizeOf(paraFormat2);
    paraFormat2.dwMask = PFM_LINESPACING;
    paraFormat2.bLineSpacingRule = 4; // twips less than 1 line space
    paraFormat2.dyLineSpacing = 200; // no line space

    IntPtr intPtr = Marshal.AllocHGlobal(Marshal.SizeOf(paraFormat2));

    Marshal.StructureToPtr(paraFormat2, intPtr, true);

    SendMessage(richTextBox1.Handle, EM_SETPARAFORMAT, SCF_ALL, intPtr);

    Marshal.FreeHGlobal(intPtr);
}