c# RTB - paste plain text without colours/fonts?

时光怂恿深爱的人放手 提交于 2020-01-01 01:08:10

问题


I am using Rich Text object in my C# application. The only issue I am having is that when user pastes formated text from another app, it remains formated which I cannot have. Is there any way how to paste only string and ignore formatting? Thanks!


回答1:


Assuming WinForms : try this : define a RichTextBox with a KeyDown event handler like this :

Append-only example :

    private void richTextBox1_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Control && e.KeyCode == Keys.V) 
        {
            richTextBox1.Text += (string)Clipboard.GetData("Text"); 
            e.Handled = true; 
        }
    }

[Edit]

Add Clipboard RTF to RichTextBox at current insertion point (selection start) example :

private void richTextBox1_KeyDown(object sender, KeyEventArgs e) 
{ 
    if (e.Control && e.KeyCode == Keys.V)  
    { 
            // suspend layout to avoid blinking
            richTextBox2.SuspendLayout();

            // get insertion point
            int insPt = richTextBox2.SelectionStart;

            // preserve text from after insertion pont to end of RTF content
            string postRTFContent = richTextBox2.Text.Substring(insPt);

            // remove the content after the insertion point
            richTextBox2.Text = richTextBox2.Text.Substring(0, insPt);

            // add the clipboard content and then the preserved postRTF content
            richTextBox2.Text += (string)Clipboard.GetData("Text") + postRTFContent;

            // adjust the insertion point to just after the inserted text
            richTextBox2.SelectionStart = richTextBox2.TextLength - postRTFContent.Length;

            // restore layout
            richTextBox2.ResumeLayout();

            // cancel the paste
            e.Handled = true;
    } 
} 

[End Edit]

Note 0 : The pasted in text is going to assume the current style settings in effect for the RichTextBox : if you have 'ForeGround color set to 'Blue : the pasted in text is going to be in blue.

Note 1 : This is something I knocked together quickly, and tested only a few times by creating some multi-colored and weirdly formatted RTF for the clipboard using WordPad : then pasting into into the RichTextBox1 at run-time : it did strip away all the color, indenting, etc.

Since it's not fully tested, use caution.

Note 2 : This will not handle the case of 'Insert or 'Paste via Context Menu, obviously.

Welcome all critiques of this answer, and will immediately take it down if it's not "on the mark."




回答2:


Add a handler to the KeyDown-event to intercept the standard paste and manually insert only the plain text:

private void rtb_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Control && e.KeyCode == Keys.V)
    {
        ((RichTextBox)sender).Paste(DataFormats.GetFormat("Text"));
            e.Handled = true;
    }
}



回答3:


I was searching for a plaintext-only richtextbox but haven't found the solution online.

Why Plaintext-only RichTextBox instead of a TextBox? For example because RichTextBox has usable undo/redo functionality and much more.

Finally I found a perfect solution by digging into the C header files of the richedit control: A RichTextBox can be switched into plaintext mode, after that it doesn't accept formatted text and images and similar things from the clipboard and behaves like a normal TextBox formattingwise. Fancy things like images can not be pasted and it pastes formatted text by removing the formatting.

class PlainRichTextBox : RichTextBox
{
    const int WM_USER = 0x400;
    const int EM_SETTEXTMODE = WM_USER + 89;
    const int EM_GETTEXTMODE = WM_USER + 90;

    // EM_SETTEXTMODE/EM_GETTEXTMODE flags
    const int TM_PLAINTEXT = 1;
    const int TM_RICHTEXT = 2;          // Default behavior 
    const int TM_SINGLELEVELUNDO = 4;
    const int TM_MULTILEVELUNDO = 8;    // Default behavior 
    const int TM_SINGLECODEPAGE = 16;
    const int TM_MULTICODEPAGE = 32;    // Default behavior 

    [DllImport("user32.dll")]
    static extern IntPtr SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);

    bool m_PlainTextMode;

    // If this property doesn't work for you from the designer for some reason
    // (for example framework version...) then set this property from outside
    // the designer then uncomment the Browsable and DesignerSerializationVisibility
    // attributes and set the Property from your component initializer code
    // that runs after the designer's code.
    [DefaultValue(false)]
    //[Browsable(false)]
    //[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public bool PlainTextMode
    {
        get
        {
            return m_PlainTextMode;
        }
        set
        {
            m_PlainTextMode = value;
            if (IsHandleCreated)
            {
                IntPtr mode = value ? (IntPtr)TM_PLAINTEXT : (IntPtr)TM_RICHTEXT;
                SendMessage(Handle, EM_SETTEXTMODE, mode, IntPtr.Zero);
            }
        }
    }

    protected override void OnHandleCreated(EventArgs e)
    {
        // For some reason it worked for me only if I manipulated the created
        // handle before calling the base method.
        PlainTextMode = m_PlainTextMode;
        base.OnHandleCreated(e);
    }
}



回答4:


The answer from pasztorpisti worked like a charm for me. Since I'm using vb.net I thought I'd post my translated code for others:

Imports System.Runtime.InteropServices
Imports System.ComponentModel

Public Class MyRichTextBox
    Inherits Windows.Forms.RichTextBox

    Public Const WM_USER As Integer = &H400
    Public Const EM_SETTEXTMODE As Integer = WM_USER + 89
    Public Const EM_GETTEXTMODE As Integer = WM_USER + 90

    'EM_SETTEXTMODE/EM_GETTEXTMODE flags
    Public Const TM_PLAINTEXT As Integer = 1
    Public Const TM_RICHTEXT As Integer = 2          ' Default behavior 
    Public Const TM_SINGLELEVELUNDO As Integer = 4
    Public Const TM_MULTILEVELUNDO As Integer = 8    ' Default behavior 
    Public Const TM_SINGLECODEPAGE As Integer = 16
    Public Const TM_MULTICODEPAGE As Integer = 32    ' Default behavior

    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
    Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
    End Function

    Private _plainTextMode As Boolean = False
    <DefaultValue(False),
      Browsable(True)>
    Public Property PlainTextMode As Boolean
        Get
            Return _plainTextMode
        End Get
        Set(value As Boolean)
            _plainTextMode = value

            If (Me.IsHandleCreated) Then
                Dim mode As IntPtr = If(value, TM_PLAINTEXT, TM_RICHTEXT)
                SendMessage(Handle, EM_SETTEXTMODE, mode, IntPtr.Zero)
            End If
        End Set
    End Property

    Protected Overrides Sub OnHandleCreated(e As EventArgs)
        'For some reason it worked for me only if I manipulated the created
        'handle before calling the base method.
        Me.PlainTextMode = _plainTextMode

        MyBase.OnHandleCreated(e)
    End Sub
End Class



回答5:


Well the RichTextBox has a SelectionFont property so you can for instance do the following:

Font courier;
courier = new Font("Courier new", 10f, FontStyle.Regular);
myRtb.SelectionFont = courier;
myRtb.Font = courier; //So the typed text is also the same font

If a text gets pasted, it will be automatically formatted.




回答6:


You can also use

private void richTextBox1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Control && e.KeyCode == Keys.V)
    {
        richTextBox1.SelectedText = (string)Clipboard.GetData("Text");
        e.Handled = true;
    }
}



回答7:


I achieved this by udpating the font and colour for the whole RTB when its contents are changed. This works fine for me as the entry box does not need to deal with huge amounts of text.

public FormMain()
{
    InitializeComponent();
    txtRtb.TextChanged += txtRtb_TextChanged;
}

void txtRtb_TextChanged(object sender, EventArgs e)
{
    RichTextBox rtb = (RichTextBox)sender;
    rtb.SelectAll();
    rtb.SelectionFont = rtb.Font;
    rtb.SelectionColor = System.Drawing.SystemColors.WindowText;
    rtb.Select(rtb.TextLength,0);
}



回答8:


My solution

private void OnCommandExecuting(object sender, Telerik.Windows.Documents.RichTextBoxCommands.CommandExecutingEventArgs e)
{
    if (e.Command is PasteCommand)
    {
        //override paste when clipboard comes from out of RichTextBox (plain text)
        var documentFromClipboard = ClipboardEx.GetDocumentFromClipboard("RadDocumentGUID");
        if (documentFromClipboard == null)
        {
            (sender as RichTextBox).Insert(Clipboard.GetText());
            e.Cancel = true;
        }
    }
}



回答9:


There is a very simple way to do this that is working well for me:

private bool updatingText;

public MyForm() {
    InitializeComponent();
    inputTextBox.TextChanged += inputTextBox_TextChanged;
}
private void inputTextBox_TextChanged(object sender, EventArgs e)
{
    if (updatingText)
    {
        return;
    }
    updatingText = true;
    try
    {
        var i = inputTextBox.SelectionStart;
        var text = inputTextBox.Text;
        inputTextBox.Rtf = "";
        inputTextBox.Text = text;
        inputTextBox.SelectionStart = i;
    }
    catch (Exception){}
    updatingText = false;
}

Since the Text property is inherently without formatting resetting the RTF text then setting the text property to the raw input removes any of the special items that may have been pasted in.




回答10:


Simple, but everything in the clipboard is in plain text when application is open.

private void timer2_Tick(object sender, EventArgs e)
        {
            string paste = Clipboard.GetText();
            Clipboard.SetText(paste);
        }


来源:https://stackoverflow.com/questions/2037827/c-sharp-rtb-paste-plain-text-without-colours-fonts

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!