RichTextBox(winform)保存段落格式(PARAFORMAT2)

时间:2011-03-14 22:00:14

标签: winforms richtextbox winforms-interop

我正在使用RichTextBox控件,除了行间距外,它很棒。我正在使用带有PARAFORMAT2的SendMessage进行互操作调用来设置段落的行间距。

这很有效。它确实完全符合我的要求。问题是,当我保存RTF字符串,然后将其重新输入时,行间距信息消失了。

我可以通过添加第二个RichText Box并使用下面的代码来证明这一点。在richTextBox1中,rtf字符串格式正确。但是当它到达richTextBox2时,它再次单行间隔。

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

        richTextBox2.Rtf = rtf;
    }

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

保留格式的任何建议?我知道我可以使用/ ls设置进入并修改RTF字符串,但这非常痛苦。是否有一个更清洁的解决方案,我只是在某处丢失?

更新

EM_STREAMIN / OUT建议很棒,但遗憾的是导致同样的精神错乱。正如我在STREAMIN和STREAMOUT上阅读的更多内容,我发现控件提供的SaveFile和LoadFile是这两个消息命令的简单包装器,所以为了简单起见,我在这个示例中使用了这两个命令。我正在附上一个示例应用程序。您应该能够将此代码剪切并粘贴到带有一个文本框和五个按钮的表单中:

加载,保存,清除,DoubleSpace和SingleSpace

我正在使用MemoryStream对象来处理Save和Load点击之间的临时数据。测试:(1)使用DoubleSpace按钮更改一个或多个段落的间距。 (2)将RichText保存到MemoryStream。 (3)清除富文本控件(4)将MemoryStream数据重新加载回控件。

请注意,重新加载时,它会丢失双倍格式。所有其他格式仍然存在。

2 个答案:

答案 0 :(得分:0)

因为有人建议您需要发布一些代码,因为从您的描述中可以很难说出问题所在。

根据我的理解,使用richtextbox的Rtf属性应该完全符合您的需要。默认实施是使用 EM_STREAMOUT EM_STREAMIN 消息将内容以 SF_RTF 格式流入和流出richedit。您也可以尝试使用此SO问题中的代码进行手动操作:Example of using EM_STREAMOUT with c# and RichEditBox

希望这有帮助,尊重

答案 1 :(得分:0)

这是我发现的...我的SetParagraphSpacing没有设置我需要的一切。这足以让RichTextBox正常显示,但我猜有些标志没有被设置。相反,我将其更改为以下内容,现在似乎完美地工作了。

您必须在bLineSpacingRule中使用dyLineSpacing IN CONJUNCTION。 bLineSpacing规则似乎是生命的显示方面,而dyLineSpacing是保存/加载期间使用的标志。如果您不使用其中任何一个,它将无法正常保存/加载或无法正确显示。我不确定所有这些背后的机制,(如果有人可以解释,我会很感激),但就目前而言,这是我所做的改变。

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