Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 4067090
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 20, 20262026-05-20T16:12:23+00:00 2026-05-20T16:12:23+00:00

I’m working with a RichTextBox control, and it’s going great, except for the line

  • 0

I’m working with a RichTextBox control, and it’s going great, except for the line spacing. I’m using an interop call via SendMessage with PARAFORMAT2 to set the line spacing for a paragraph.

That works great. It does EXACTLY what I need it to do. The problem is, when I save the RTF string out, then bring it back in, the line spacing information is gone.

I can prove this by adding a second RichText Box, and using the code below. In richTextBox1, the rtf string is formatted properly. But by the time it gets to richTextBox2, it’s single-spaced again.

    private void button15_Click(object sender, EventArgs e)
    {
        string rtf = richTextBox1.Rtf;

        richTextBox2.Rtf = rtf;
    }

Any suggestions for keeping the formatting? I know I can go in and mangle the RTF string using the /ls setting, but that is VERY painful. Is there a cleaner solution that I’m just missing somewhere?

UPDATE:

The EM_STREAMIN/OUT suggestions are awesome, but unfortunately result in the same insanity. As I’ve read more on STREAMIN and STREAMOUT, I’ve discovered that SaveFile and LoadFile provided by the control are simple wrappers for these two message commands, so for simplicity I’m using those two commands in this sample. I’m attaching a sample application. You should be able to pretty much cut and paste this code into a form with one text box and five buttons:

Load, Save, Clear, DoubleSpace and SingleSpace

I’m using the MemoryStream object to handle the temporary data between the Save and Load clicks. The test: (1) Use the DoubleSpace button to change the spacing of one or more paragraphs. (2) Save the RichText to the MemoryStream. (3) Clear the rich text control (4) re-load the MemoryStream data back into the control.

Note that when it is re-loaded, it has lost the double-space formatting. All other formatting remains.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;

namespace WindowsFormsApplication4
{
    public partial class Form2 : Form
    {
        MemoryStream ms = new MemoryStream();
        public Form2()
        {
            InitializeComponent();

            // First, load some crap in...
            richTextBox1.Text = "The quick red fox jumped over the lazy brown dog. The quick red fox jumped over the lazy brown dog. The quick red fox jumped over the lazy brown dog. The quick red fox jumped over the lazy brown dog. \r\nThe quick red fox jumped over the lazy brown dog. The quick red fox jumped over the lazy brown dog. The quick red fox jumped over the lazy brown dog. \r\nThe quick red fox jumped over the lazy brown dog. The quick red fox jumped over the lazy brown dog. The quick red fox jumped over the lazy brown dog. ";
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            ms.Seek(0, SeekOrigin.Begin);
            richTextBox1.LoadFile(ms, RichTextBoxStreamType.RichText);
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            if (ms.Length > 0) ms.Dispose();

            ms = new MemoryStream();
            richTextBox1.SaveFile(ms, RichTextBoxStreamType.RichText);

        }

        private void btnSingleSpace_Click(object sender, EventArgs e)
        {
            SetParagraphSpacing(richTextBox1, 0);
        }

        private void btnDoubleSpace_Click(object sender, EventArgs e)
        {
            SetParagraphSpacing(richTextBox1, 2);
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            richTextBox1.Text = "";
        }

        [DllImport("USER32.dll")]
        private static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wp, IntPtr lp);

        public void SetParagraphSpacing(RichTextBox rtb, int Spacing)
        {
            PARAFORMAT2 paraform = new PARAFORMAT2();
            paraform.cbSize = Marshal.SizeOf(paraform);
            paraform.bLineSpacingRule = Convert.ToByte(Spacing);
            paraform.wReserved = 0;
            paraform.dwMask = ParaMessages.PFM_LINESPACING;

            IntPtr res = IntPtr.Zero;

            IntPtr wparam = IntPtr.Zero;

            //Get the pointer to the FORMATRANGE structure in memory
            IntPtr lparam = IntPtr.Zero;
            lparam = Marshal.AllocCoTaskMem(Marshal.SizeOf(paraform));
            Marshal.StructureToPtr(paraform, lparam, false);

            //Send the rendered data for printing 
            res = SendMessage(rtb.Handle, ParaMessages.EM_SETPARAFORMAT, wparam, lparam);

            //Free the block of memory allocated
            Marshal.FreeCoTaskMem(lparam);
        }

        [StructLayout(LayoutKind.Sequential)]

        public struct PARAFORMAT2
        {
            public int cbSize;
            public uint dwMask;
            public short wNumbering;
            public short wReserved;
            public int dxStartIndent;
            public int dxRightIndent;
            public int dxOffset;
            public short wAlignment;
            public short cTabCount;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
            public int[] rgxTabs;

            // PARAFORMAT2 from here onwards.
            public int dySpaceBefore;
            public int dySpaceAfter;
            public int dyLineSpacing;
            public short sStyle;
            public byte bLineSpacingRule;
            public byte bOutlineLevel;
            public short wShadingWeight;
            public short wNumberingStart;
            public short wNumberingStyle;
            public short wNumberingTab;
            public short wBorderSpace;
            public short wBorderWidth;
            public short wBorders;
        }

        public class ParaMessages
        {
            public static uint PFM_SPACEAFTER = 128;
            public static uint PFM_LINESPACING = 256;

            // Constants from the Platform SDK.
            public static uint EM_SETEVENTMASK = 1073;
            public static uint EM_GETPARAFORMAT = 1085;
            public static uint EM_SETPARAFORMAT = 1095;
            public static uint EM_SETTYPOGRAPHYOPTIONS = 1226;
            public static uint WM_SETREDRAW = 11;
            public static uint TO_ADVANCEDTYPOGRAPHY = 1;
            public static uint PFM_ALIGNMENT = 8;
            public static uint SCF_SELECTION = 1;
        }
    }
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-20T16:12:24+00:00Added an answer on May 20, 2026 at 4:12 pm

    Here’s what I found… my SetParagraphSpacing wasn’t setting everything I needed. It was enough to get the RichTextBox to display properly, but I guess there were some flags not being set. Instead, I changed it to the following, and it seems to be working PERFECTLY, now.

    You have to use dyLineSpacing IN CONJUNCTION with bLineSpacingRule. bLineSpacing rule seems to be the display side of life, while dyLineSpacing is the flag that is used during the save/load. If you leave off either of these, it doesn’t save/load properly or doesn’t display properly. I’m not sure the mechanics behind all of this, (if someone can explain, I’d be grateful), but for now, this is the change I’ve made.

    public void SetParagraphSpacing(RichTextBox rtb, int Spacing)
    {
        PARAFORMAT2 paraform = new PARAFORMAT2();
        paraform.cbSize = Marshal.SizeOf(paraform);
    
        // NOTE: You need both of these!
        paraform.bLineSpacingRule = Convert.ToByte(Spacing);
        paraform.dyLineSpacing = Spacing;
    
        paraform.wReserved = 0;
        paraform.dwMask = ParaMessages.PFM_LINESPACING;
    
        IntPtr res = IntPtr.Zero;
    
        IntPtr wparam = IntPtr.Zero;
    
        //Get the pointer to the FORMATRANGE structure in memory
        IntPtr lparam = IntPtr.Zero;
        lparam = Marshal.AllocCoTaskMem(Marshal.SizeOf(paraform));
        Marshal.StructureToPtr(paraform, lparam, false);
    
        //Send the rendered data for printing 
        res = SendMessage(rtb.Handle, ParaMessages.EM_SETPARAFORMAT, wparam, lparam);
    
        //Free the block of memory allocated
        Marshal.FreeCoTaskMem(lparam);
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

No related questions found

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.