【问题标题】:RichTextBox - retain original formatting (font), even after pasteRichTextBox - 保留原始格式(字体),即使在粘贴之后
【发布时间】:2010-12-30 18:12:31
【问题描述】:

我需要使用 RichTextBox,而不是普通的文本框,因为它保持插入符号位置的方式,逐行。 但是我需要让文字一直保持相同的字体,即使是粘贴的。

目前我让它选择整个文本并将字体更改为原始字体(Lucida Console),但是当你粘贴到它时它看起来很糟糕,因为它闪烁蓝色。

【问题讨论】:

    标签: vb.net fonts richtextbox paste


    【解决方案1】:

    如果您以编程方式处理粘贴,请不要使用Paste 方法。而是使用 Clipboard.GetDataObject().GetData(DataFormats.Text) 来获取字符串中的文本,然后使用 Rtf 或 Text 属性将文本添加到 RichTextBox:

    string s = (string)Clipboard.GetDataObject().GetData(DataFormats.Text);
    richTextBox.Text += s;
    

    否则你可以处理 Ctrl+V 按键:

    void RichTextBox1_KeyDown(object sender, KeyEventArgs e)
    {
        if(e.Control == true && e.KeyCode == Keys.V)
        {
            string s = (string)Clipboard.GetDataObject().GetData(DataFormats.Text);
            richTextBox.Text += s;
            e.Handled = true; // disable Ctrl+V
        }
    }
    

    【讨论】:

    • 可以改用richTextBox.SelectedText = s;,否则粘贴后光标会跳回到开头。
    【解决方案2】:

    Darin 的方法忽略插入符号的位置,并且总是附加到文本的末尾。

    其实还有更好的方法。使用 RichTextBox.Paste() 的重载:

    DataFormats.Format plaintext_format = DataFormats.GetFormat(DataFormats.Text);
    this.Paste(plaintext_format);
    

    对我来说就像魅力一样。

    【讨论】:

      【解决方案3】:

      @Darin 和@idn 的答案都很好,但是在粘贴以下富文本时我都无法工作:

         This is text after an arrow.
      This is a new line
      

      字体将始终更改为 WingDings。我从 MS Word 复制了这个:

      具体来说,上面@idn 描述的纯文本格式方法确实只是粘贴纯文本,但是字体也发生了变化。

      以下代码处理 KeyUp 事件以仅选择所有文本并替换其原始颜色和字体(即格式)。为确保屏幕上不会出现闪烁,使用了special method of disabling window repaint events。控件绘制禁用发生在KeyDown事件中,RichTextBox控件自己处理粘贴事件,最后重新启用控件绘制。最后,这仅适用于 CTL+V 和 SHIFT+INS,它们都是标准粘贴命令:

          /// <summary>
          /// An application sends the WM_SETREDRAW message to a window to allow changes in that 
          /// window to be redrawn or to prevent changes in that window from being redrawn.
          /// </summary>
          private const int WM_SETREDRAW = 11; 
      
          private void txtRichTextBox_KeyDown(object sender, KeyEventArgs e)
          {
              // For supported Paste key shortcut combinations, suspend painting
              // of control in preparation for RTF formatting updates on KeyUp
              if ((e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.V) || // CTL+V
                  (!e.Control && e.Shift && !e.Alt && e.KeyCode == Keys.Insert)) // SHIFT+INS
              {
                  // Send Suspend Redraw message to avoid flicker. Drawing is 
                  // restored in txtRichTextBox_KeyUp event handler
                  // [this.SuspendLayout() doesn't work properly] 
                  Message msgSuspendUpdate = Message.Create(
                      txtRichTextBox.Handle, WM_SETREDRAW, IntPtr.Zero, IntPtr.Zero);
                  NativeWindow window = NativeWindow.FromHandle(txtRichTextBox.Handle);
                  window.DefWndProc(ref msgSuspendUpdate);
              }
          }
      
          private void txtRichTextBox_KeyUp(object sender, KeyEventArgs e)
          {
              // Following supported Paste key shortcut combinations, restore
              // original formatting, then resume painting of control.
              if ((e.Control && !e.Shift && !e.Alt && e.KeyCode == Keys.V) || // CTL+V
                  (!e.Control && e.Shift && !e.Alt && e.KeyCode == Keys.Insert)) // SHIFT+INS
              {
                  // Layout already suspended during KeyDown event
      
                  // Capture cursor position. Cursor will later be placed 
                  // after inserted text
                  int selStart = txtRichTextBox.SelectionStart;
                  int selLen = txtRichTextBox.SelectionLength;
      
                  // Replace all text with original font & colours
                  txtRichTextBox.SelectAll();
                  txtRichTextBox.SelectionFont = txtRichTextBox.Font;
                  txtRichTextBox.SelectionColor = txtRichTextBox.ForeColor;
                  txtRichTextBox.SelectionBackColor = txtRichTextBox.BackColor;
      
                  // Restore original selection
                  txtRichTextBox.SelectionStart = selStart;
                  txtRichTextBox.SelectionLength = selLen;
      
                  txtRichTextBox.ScrollToCaret();
      
                  // Resume painting of control
                  IntPtr wparam = new IntPtr(1); // Create a C "true" boolean as an IntPtr
                  Message msgResumeUpdate = Message.Create(
                      txtRichTextBox.Handle, WM_SETREDRAW, wparam, IntPtr.Zero);
                  NativeWindow window = NativeWindow.FromHandle(txtRichTextBox.Handle);
                  window.DefWndProc(ref msgResumeUpdate);
                  txtRichTextBox.Invalidate();
                  txtRichTextBox.Refresh();
              }
          }
      

      这种方法的一个注意事项是,由于事件未被抑制 (e.Handled = true;),因此支持标准 CTL+Z(撤消)操作。但是,此过程也会通过撤消格式更改来循环。我不认为这是一个大问题,因为下次粘贴该文本时,格式会再次被删除。

      这种方法并不完美,因为如果从 RichTextBox 复制并粘贴文本(到另一个应用程序),新应用的格式仍然存在,但在我看来,这比失去撤消功能要好。如果撤消功能不重要,则将文本选择和格式化应用程序替换为文本替换以删除所有格式,根据此答案:https://stackoverflow.com/a/1557270/3063884

      var t = txtRichTextBox.Text;
      txtRichTextBox.Text = t; 
      

      【讨论】:

        猜你喜欢
        • 2011-07-25
        • 1970-01-01
        • 1970-01-01
        • 2023-04-04
        • 1970-01-01
        • 1970-01-01
        • 2021-12-17
        • 2016-08-27
        • 2012-04-25
        相关资源
        最近更新 更多