C#:在 RichTextBox 中粘贴 RTF,但保留颜色和格式(即:粗体、下划线等)

发布于 2024-10-28 00:03:58 字数 227 浏览 5 评论 0原文

是否可以将文本粘贴到富文本框中,同时保留粘贴内容在富文本框中使用的字体?

换句话说,我想从 Word 中复制一些已格式化的内容(即:使用字体 X 并带有下划线和蓝色的文本),然后将其粘贴到我的 RichTextBox 中。

我希望粘贴的内容具有与 RichTextBox 相同的字体,但保留其原始颜色和下划线。

这样的事可能吗?

我用的是winform。

谢谢

Is it possible to paste text into a Rich Text Box, while keeping the font being used in the Rich Text Box for the pasted content ?

In other words, I'd like to copy something from Word that is formated (i.e: a text that uses a font X and is underlined and in blue), and then paste it in my RichTextBox.

I would like the pasted content to have the same font as that of my RichTextBox but keep its original coloring and underlining.

Is such a thing possible ?

I use winforms.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

ぇ气 2024-11-04 00:03:58

这是不可能开箱即用的。但您可以执行以下操作:

public void SpecialPaste()
{
    var helperRichTextBox = new RichTextBox();
    helperRichTextBox.Paste();
    for(int i=0;i<helperRichTextBox.TextLength;++i)
    {
        helperRichTextBox.SelectionStart = i;
        helperRichTextBox.SelectionLength = 1;
        helperRichTextBox.SelectionFont = new Font(richTextBox1.SelectionFont.FontFamily, richTextBox1.SelectionFont.Size,helperRichTextBox.SelectionFont.Style);
    }

    richTextBox1.SelectedRtf = helperRichTextBox.Rtf;
}

这会将粘贴的 RTF 的字体更改为粘贴时插入符号位置之前的字符的字体。
我认为如果您粘贴的文本很大(呃),那么很快就会出现问题。此外,这可以通过某种方式进行优化,即按照 Hans 的建议,为具有相同基本字体的行中的所有字符仅设置一次字体。

更新:
这是优化的版本,它为具有相同原始字体的连接字符集设置字体:

public void SpecialPaste()
{
    var helperRichTextBox = new RichTextBox();
    helperRichTextBox.Paste();
    helperRichTextBox.SelectionStart = 0;
    helperRichTextBox.SelectionLength = 1;

    Font lastFont = helperRichTextBox.SelectionFont;
    int lastFontChange = 0;
    for (int i = 0; i < helperRichTextBox.TextLength; ++i)
    {
        helperRichTextBox.SelectionStart = i;
        helperRichTextBox.SelectionLength = 1;
        if (!helperRichTextBox.SelectionFont.Equals(lastFont))
        {
            lastFont = helperRichTextBox.SelectionFont;
            helperRichTextBox.SelectionStart = lastFontChange;
            helperRichTextBox.SelectionLength = i - lastFontChange;
            helperRichTextBox.SelectionFont = new Font(richTextBox1.SelectionFont.FontFamily, richTextBox1.SelectionFont.Size, helperRichTextBox.SelectionFont.Style);
            lastFontChange = i;
        }
    }
    helperRichTextBox.SelectionStart = helperRichTextBox.TextLength-1;
    helperRichTextBox.SelectionLength = 1;
    helperRichTextBox.SelectionFont = new Font(richTextBox1.Font.FontFamily, richTextBox1.Font.Size, helperRichTextBox.SelectionFont.Style);

    richTextBox1.SelectedRtf = helperRichTextBox.Rtf;
}

这是非常丑陋的代码,我相信它可以改进和清理。但它做了它应该做的事。

This is not possible out of the box. But you can do something like this:

public void SpecialPaste()
{
    var helperRichTextBox = new RichTextBox();
    helperRichTextBox.Paste();
    for(int i=0;i<helperRichTextBox.TextLength;++i)
    {
        helperRichTextBox.SelectionStart = i;
        helperRichTextBox.SelectionLength = 1;
        helperRichTextBox.SelectionFont = new Font(richTextBox1.SelectionFont.FontFamily, richTextBox1.SelectionFont.Size,helperRichTextBox.SelectionFont.Style);
    }

    richTextBox1.SelectedRtf = helperRichTextBox.Rtf;
}

This changes the font of the pasted RTF to that of the character preceding the caret position at the time of the paste.
I assume that will get problematic pretty fast, if the text you paste is large(er). Additionally, this can be optimized in a way, that it sets the font only once for all characters in a row with the same base font as Hans suggests.

Update:
Here is the optimized version, that sets the font for a connected set of characters with the same original font:

public void SpecialPaste()
{
    var helperRichTextBox = new RichTextBox();
    helperRichTextBox.Paste();
    helperRichTextBox.SelectionStart = 0;
    helperRichTextBox.SelectionLength = 1;

    Font lastFont = helperRichTextBox.SelectionFont;
    int lastFontChange = 0;
    for (int i = 0; i < helperRichTextBox.TextLength; ++i)
    {
        helperRichTextBox.SelectionStart = i;
        helperRichTextBox.SelectionLength = 1;
        if (!helperRichTextBox.SelectionFont.Equals(lastFont))
        {
            lastFont = helperRichTextBox.SelectionFont;
            helperRichTextBox.SelectionStart = lastFontChange;
            helperRichTextBox.SelectionLength = i - lastFontChange;
            helperRichTextBox.SelectionFont = new Font(richTextBox1.SelectionFont.FontFamily, richTextBox1.SelectionFont.Size, helperRichTextBox.SelectionFont.Style);
            lastFontChange = i;
        }
    }
    helperRichTextBox.SelectionStart = helperRichTextBox.TextLength-1;
    helperRichTextBox.SelectionLength = 1;
    helperRichTextBox.SelectionFont = new Font(richTextBox1.Font.FontFamily, richTextBox1.Font.Size, helperRichTextBox.SelectionFont.Style);

    richTextBox1.SelectedRtf = helperRichTextBox.Rtf;
}

It's pretty ugly code and I am sure it can be improved and cleaned. But it does what it should.

梦与时光遇 2024-11-04 00:03:58

显然,如果剪贴板上的 RTF 包含带有 /font 指令的片段,则这不会按您希望的方式工作。这很有可能。只有通过粘贴到辅助 RichTextBox 中才能过滤 RTF 片段。使用 SelectionFont 属性,然后将其复制回剪贴板并粘贴()。或者直接执行:

        int oldpos = richTextBox1.SelectionStart;
        richTextBox1.SelectionLength = 0;
        richTextBox1.Paste();
        int newpos = richTextBox1.SelectionStart;
        richTextBox1.SelectionStart = oldpos;
        richTextBox1.SelectionLength = newpos - oldpos;
        richTextBox1.SelectionFont = richTextBox1.Font;
        richTextBox1.SelectionStart = newpos;

Clearly this won't work the way you want it if the RTF on the clipboard contains a fragment with a /font directive. Which is very likely. Filtering the RTF fragment is only practical by pasting into a helper RichTextBox. Use the SelectionFont property then copy it back to the clipboard and Paste(). Or do it directly:

        int oldpos = richTextBox1.SelectionStart;
        richTextBox1.SelectionLength = 0;
        richTextBox1.Paste();
        int newpos = richTextBox1.SelectionStart;
        richTextBox1.SelectionStart = oldpos;
        richTextBox1.SelectionLength = newpos - oldpos;
        richTextBox1.SelectionFont = richTextBox1.Font;
        richTextBox1.SelectionStart = newpos;
晨敛清荷 2024-11-04 00:03:58

我知道这有点晚了,但我遇到了同样的问题,这是我的解决方案(希望这对其他人有帮助):

首先,处理 RichTextBox 的 KeyDown 事件:

this.richTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.RichTextBoxKeyDown);

接下来,检查粘贴键事件并重新设置剪贴板文本(这就是神奇发生的地方):

     private void RichTextBoxKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Control && e.KeyCode == Keys.V)
            {
                try
                {
                    Clipboard.SetText(Clipboard.GetText());
                }
                catch (Exception)
                {
                }
            }
        }

说明:
首先我要说的是,这仅使用 .NET 4.0 进行了测试。假设所使用的任何功能都没有改变,这也适用于旧版本的 .NET。

调用 Clipboard.GetText() 以纯文本格式返回内容(不包括 RTF 标签)。然后,我们使用从 Clipboard.GetText() 获取的纯文本调用 Clipboard.SetText() 来更改要粘贴的文本。现在,当事件完成并传递给控件时,它将执行粘贴操作,从剪贴板(我们的更改版本)中获取最新文本。它被包装在 try/catch 块中的原因是因为 SetText 有时会抛出异常,即使它成功地将文本复制到剪贴板。您当然可以使用剪贴板提供的其他方法来获取/设置文本,这只是解决方案的基本版本。

新粘贴的文本将继承光标位置的格式,类似于手动输入 RTB。

不幸的是,这也会删除文本的样式(粗体、着色等)

希望这有帮助!

I know this is a bit late, but I ran into the same problem and here is my solution (hopefully this will help others):

First, handle the KeyDown event for the RichTextBox:

this.richTextBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.RichTextBoxKeyDown);

Next, check for paste key event and re-set the clipboard text (this is where the magic happens):

     private void RichTextBoxKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Control && e.KeyCode == Keys.V)
            {
                try
                {
                    Clipboard.SetText(Clipboard.GetText());
                }
                catch (Exception)
                {
                }
            }
        }

Explanation:
I'll start by saying that this was only tested with .NET 4.0. Assuming that none of the functions being used were altered, this will also work with older versions of .NET.

Calling Clipboard.GetText() returns the content in a plain text format (excluding RTF tags). Then we alter the text that's going to be pasted by calling Clipboard.SetText() with the plain text we fetched from Clipboard.GetText(). Now, when the event is done and is passed to the control, it will perform the paste fetching the latest text from the clipboard (our altered version). The reason it is wrapped in a try/catch block is because SetText sometimes throws an exception even though it successfully copied the text to the clipboard. You can of course use the other methods provided by Clipboard to get/set the text, this is just a basic version of the solution.

The newly pasted text will inherit the format of the cursor position, similar to manually typing into the RTB.

Unfortunately this will remove the style of the text as well (bold, coloring, etc)

Hope this helps!

若言繁花未落 2024-11-04 00:03:58

我知道老了; Daniel 的答案对我有用,但前提是我替换 richTextBox1.Selection 的任何实例并简单地引用整个 richTextBox1 的字体和大小。在这种情况下,我粘贴的任何 RTF 将继承 richTextBox1 当前使用的 fontfamily 和 fontsize,同时保留 RTF 样式。

public void SpecialPaste()
{
    var helperRichTextBox = new RichTextBox();
    helperRichTextBox.Paste();
    helperRichTextBox.SelectionStart = 0;
    helperRichTextBox.SelectionLength = 1;

Font lastFont = helperRichTextBox.SelectionFont;
int lastFontChange = 0;
for (int i = 0; i < helperRichTextBox.TextLength; ++i)
{
    helperRichTextBox.SelectionStart = i;
    helperRichTextBox.SelectionLength = 1;
    if (!helperRichTextBox.SelectionFont.Equals(lastFont))
    {
        lastFont = helperRichTextBox.SelectionFont;
        helperRichTextBox.SelectionStart = lastFontChange;
        helperRichTextBox.SelectionLength = i - lastFontChange;
        helperRichTextBox.SelectionFont = new Font(richTextBox1.Font.FontFamily, richTextBox1.Font.Size, helperRichTextBox.SelectionFont.Style);
        lastFontChange = i;
    }
}
helperRichTextBox.SelectionStart = helperRichTextBox.TextLength-1;
helperRichTextBox.SelectionLength = 1;
helperRichTextBox.SelectionFont = new Font(richTextBox1.Font.FontFamily, richTextBox1.Font.Size, helperRichTextBox.SelectionFont.Style);

richTextBox1.Rtf = helperRichTextBox.Rtf;

}

Old I know; Daniel's answer works for me, but only if I replace any instance of richTextBox1.Selection and simply make references to the font and size of the entire richTextBox1. In this case, any RTF I paste will inherit the fontfamily and fontsize currently being used by richTextBox1, while preserving and RTF styling.

public void SpecialPaste()
{
    var helperRichTextBox = new RichTextBox();
    helperRichTextBox.Paste();
    helperRichTextBox.SelectionStart = 0;
    helperRichTextBox.SelectionLength = 1;

Font lastFont = helperRichTextBox.SelectionFont;
int lastFontChange = 0;
for (int i = 0; i < helperRichTextBox.TextLength; ++i)
{
    helperRichTextBox.SelectionStart = i;
    helperRichTextBox.SelectionLength = 1;
    if (!helperRichTextBox.SelectionFont.Equals(lastFont))
    {
        lastFont = helperRichTextBox.SelectionFont;
        helperRichTextBox.SelectionStart = lastFontChange;
        helperRichTextBox.SelectionLength = i - lastFontChange;
        helperRichTextBox.SelectionFont = new Font(richTextBox1.Font.FontFamily, richTextBox1.Font.Size, helperRichTextBox.SelectionFont.Style);
        lastFontChange = i;
    }
}
helperRichTextBox.SelectionStart = helperRichTextBox.TextLength-1;
helperRichTextBox.SelectionLength = 1;
helperRichTextBox.SelectionFont = new Font(richTextBox1.Font.FontFamily, richTextBox1.Font.Size, helperRichTextBox.SelectionFont.Style);

richTextBox1.Rtf = helperRichTextBox.Rtf;

}

满栀 2024-11-04 00:03:58

我尝试从 Word 文档复制文本并在运行时将其粘贴到 RichTextBox 中。一切正常。我没有调整任何具体内容。只需将 RichTextBox 拖放到表单上,然后从 MS Word 文档中复制格式化文本即可。

I've tried to copy text from a word document and pasted it to a RichTextBox in runtime. Everything works fine. I did not adjust anything specific. Just dropped the RichTextBox onto a form and copied the formatted text from the MS Word document.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文