我正在使用 RichTextBox 控件,它运行良好,除了行距。我通过 SendMessage 和 PARAFORMAT2 使用互操作调用来设置段落的行距。
这很好用。它完全符合我的需要。问题是,当我将 RTF 字符串保存出来,然后将其重新输入时,行距信息就消失了。
我可以通过添加第二个 RichText 框并使用下面的代码来证明这一点。在richTextBox1 中,rtf 字符串的格式正确。但是当它到达richTextBox2 时,它又是单行距的。
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 对象来处理保存和加载点击之间的临时数据。测试: (1) 使用 DoubleSpace 按钮更改一个或多个段落的间距。(2) 将 RichText 保存到 MemoryStream。(3) 清除富文本控件 (4) 将 MemoryStream 数据重新加载回控件中。
请注意,当它重新加载时,它已经失去了双空格格式。所有其他格式仍然存在。
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;
}
}
}