Detecting if paste event occurred inside a rich text box

18,790

It's a little bit tricky to detect a paste operation in the RichTextBox.

First solution may be to detect the WM_PASTE message overriding the WndProc but unfortunately the control doesn't send that message to itself when it performs a paste operation.

Naïve detection

To detect the keyboard events may work (you have to override the OnKeyDown function) then check if the key combinations (CTRL+V and SHIFT+INS). Something like this:

protected override OnKeyDown(KeyEventArgs e)
{
     bool ctrlV = e.Modifiers == Keys.Control && e.KeyCode == Keys.V;
     bool shiftIns = e.Modifiers == Keys.Shift && e.KeyCode == Keys.Insert;

     if (ctrlV || shiftIns)
         DoSomething();
}

It works well but you can't catch the paste operation made using the mouse (right click to open the context menu) and the paste operations made via drag & drop. If you do not need them you can use this solution (at least it's simply and straightforward).

Better detection

Assumption: when user types inside the RichTextBox he inserts one character per time. How can you use this? Well, when you detect a bigger change you detected a paste operation because user can't type more than once character per time (ok, you can argue that it's not always true because of Unicode surrogates). See also VB.NET version and more details about Unicode stuff.

private int _previousLength = 0;

private void richTextBox_TextChanged(object sender, EventArgs e)
{
   int currentLength = richTextBox.Text.Length;
   if (Math.Abs(currentLength - _previousLength) > 1)
      ProcessAllLines();

   _previousLength = currentLength;
}

Please note that you can't (because of how different IMEs work) use OnKeyDown (or similar). This works well only for western languages but it has problems with Unicode stuff (because, for example, String.Length property may be increased by two Char when user typed a single character. See also this post for much more details about this (well it's a strongly suggested reading even, even if - in this case - you don't care about it). In that post you'll also find code for a better algorithm to determine string length. In short you have to replace:

   int currentLength = richTextBox.Text.Length;

With this:

   int currentLength = StringInfo.GetTextElementEnumerator(richTextBox.Text)
       .Cast<string>()
       .Count();

After all this effort you may realize that...user can even paste a single character and it may go undetected. You're right, that's why this is a better detection instead of a perfect solution.

Perfect solution

The perfect solution (if you're running on Windows 8) of course exists, the native rich edit control sends an EN_CLIPFORMAT notification message. It's intended to notify a rich edit control's parent window that a paste occurred with a particular clipboard format. You can then override the WndProc of its parent to detect the WM_NOTIFY message for this notification. Anyway it's not few lines of code, check this MSDN article for details.

Share:
18,790
redDragonzz
Author by

redDragonzz

Boom. Code. Test. Deploy. Splash.

Updated on June 05, 2022

Comments

  • redDragonzz
    redDragonzz almost 2 years

    Is there a way by which we can find out if a clip board paste event occurred in a rich text box? This event would be used in order to do certain stuff, with the pasted block of text.

    thanks

    Here is my code

     protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            if (m.Msg == WM_PASTE)
            {
                OnPasteOccurred();
                MessageBox.Show("Pas");
            }
            if (m.Msg == 0x000F)
            {
                if (PaintControl)
                {
                    base.WndProc(ref m);
                }
                else
                {
                    m.Result = IntPtr.Zero;
                }
            }
            else
            {
                base.WndProc(ref m);
            }
        }
    

    Edit

    I wish to do some syntax highlighting or indentation based on paste events, something which this particular code editor seems to be doing very efficiently. I don't know how it is doing it. Would require help in this particular direction. I am pretty sure that there must some native Win32 code or something like that can be intercepted. I have tried tracking down keys, mouse events and it is not pretty.

  • redDragonzz
    redDragonzz almost 12 years
    isn't the msdn one applying to windows 8 only?
  • Adriano Repetti
    Adriano Repetti almost 12 years
    @redDragonzz sadly...yes, that's a notification message for Windows 8 only. I'll update my answer to make it clear!
  • Adriano Repetti
    Adriano Repetti almost 12 years
    @redDragonzz update: I guess a "true" syntax highligh algorithm won't suffer for poor performance 'cause he won't work on the full text and it'll do it in background on another thread while you're typing. Did you take a look to the code of the (old) SharpDevelop IDE? They did provide both colors and intellisense.
  • CodesInChaos
    CodesInChaos over 9 years
    Isn't this WPF not winforms?
  • Nyerguds
    Nyerguds about 8 years
    Context menus aren't standard on the rich text box, though, and neither is drag and drop. You can perfectly control any pasting done through that. As far as I know only the shortcuts really need checking.
  • Adriano Repetti
    Adriano Repetti about 8 years
    @Nyerguds yes, they're not enabled by default but they're one property away and in many cases any non trivial use will have something more. Also keyhandling is all but not trivial for IME of east languages (I do not mention tools to help visually/motor impaired people). I don't mean that you always need extra complexity, of course! If you have a very controlled solution then even simpler approach may work (note that keyboard shortcut may be disabled an manually handled).
  • Nyerguds
    Nyerguds about 8 years
    @AdrianoRepetti Actually, RichTextBox doesn't have a built-in right-click menu like TextBox does; you can just specify a context menu object to use. So you'd have to program it yourself anyway. Same for drag & drop; you'd need to filter out the type and handle everything yourself. In fact, my project has a RTB that only accepts file drops.
  • Adriano Repetti
    Adriano Repetti about 8 years
    @Nyerguds for this question (syntax highlighting) context menu isn't built-in on RTF editor (code to do highlighting and code that adds UI would be pretty separate). Obviously yes, if you do everything by yourself (also disabling keyboard shortcuts) and you need this information on the same place then you don't need any notification from RichEdit itself!
  • Nyerguds
    Nyerguds about 8 years
    @AdrianoRepetti Given the fact RichTextBox has really simple Cut(), Copy() and Paste() functions for handling clipboard stuff anyway, just catching and overriding the paste shortcut exactly as you showed and ending the code with e.Handled=true; does seems like the simplest solution here in my opinion. Then you can do whatever you want with the pasted content.
  • Adriano Repetti
    Adriano Repetti about 8 years
    Note that I somehow agree with you, here it's just for sake of discussion. I avoid whenever possible to do it for two reasons: IMEs and tools for tools for visual/motor impaired people. Handling keydown/up is a pain with many IMEs (especially in far-east) and there are endless combinations you should test (I'm still searching an answer for this question).
  • Adriano Repetti
    Adriano Repetti about 8 years
    About other tools (also for voice dictation) I try to use standard behavior/implementation whenever possible: I can assume they extensively tested their products with standard controls but with my implementation it's an incognita...
  • Nyerguds
    Nyerguds about 8 years
    @AdrianoRepetti Ah, IMEs. Seems like a real pain. The closest I ever got to that mess is localization-specific upper/lower case rules. Godspeed on that -_-
  • Adriano Repetti
    Adriano Repetti about 8 years
    @Nyerguds yes, it is! Actually I like that topic (self-advertising: stackoverflow.com/a/27229590/1207195) but yes it's a source of thousands issues and headaches!