I need to "modify" all pasted into TextBox text to be shown in some structured way. I can do it with drag-n-drop, ctrl-v, but how to do it with default context's menu "Paste"?
Asked
Active
Viewed 1.1k times
1 Answers
21
While I would normally not suggest dropping to low level Windows API, and this may not be the only way of doing this, it does do the trick:
using System;
using System.Windows.Forms;
public class ClipboardEventArgs : EventArgs
{
public string ClipboardText { get; set; }
public ClipboardEventArgs(string clipboardText)
{
ClipboardText = clipboardText;
}
}
class MyTextBox : TextBox
{
public event EventHandler<ClipboardEventArgs> Pasted;
private const int WM_PASTE = 0x0302;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_PASTE)
{
var evt = Pasted;
if (evt != null)
{
evt(this, new ClipboardEventArgs(Clipboard.GetText()));
// don't let the base control handle the event again
return;
}
}
base.WndProc(ref m);
}
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var tb = new MyTextBox();
tb.Pasted += (sender, args) => MessageBox.Show("Pasted: " + args.ClipboardText);
var form = new Form();
form.Controls.Add(tb);
Application.Run(form);
}
}
Ultimately the WinForms toolkit is not very good. It is a thin-ish wrapper around Win32 and the Common Controls. It exposes the 80% of the API that is most useful. The other 20% is often missing or not exposed in a way that is obvious. I would suggest moving away from WinForms and to WPF if possible as WPF seems to be a better architected framework for .NET GUIs.
-
thanks, I've just learned sth new (not only how to catch "paste", nut a ne way of doin things) – David Aug 10 '10 at 11:09
-
event keyword is missing on Pasted field declaration and why are you using a local variable evt ? – Maxence Oct 03 '11 at 09:10
-
You're missing a `return` inside the `if` statement which causes the base control to re-handle this event. I was formatting XML on paste and without the `return`, both the the formatted and unformatted XML show up as the base control handles the paste again. – Mrchief Dec 23 '13 at 16:07
-
@Maxence The local variable is to avoid a race condition that can occur between checking if `Pasted == null` and invoking the handler. If the lone subscriber unsubscribes from the event on another thread between the check and invocation, you could end up with a null reference exception. C# 6 allows `Pasted?.Invoke()` as an alternative thead-safe solution. – itsme86 May 02 '17 at 22:39
-
@itsme86 even in C#6 this capturing the variable is important because not only are we preventing the race condition, but we only want to prevent the default behaviour if the `Pasted` event was registered in the first place. This implementation is therefore still relevant even as we head into C#10. – Chris Schaller Dec 17 '21 at 04:04
-
I was wondering why not simply check for ctrl+v keypress? – NoChance Jan 11 '22 at 20:54