Detecting if paste event occurred inside a rich text box
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.
Detecting a paste into a RichTextBox
Because not all people may use Ctrl+V and because there are other ways to get text into a text box (such as drag and drop), I went a different route, which I will share here in case anyone else is looking for a solution.
What I did was create a field in my class:
int _lastPosition = 0;
and in the TextChanged() event I added the following:
if (SelectionStart - _lastPosition > 2)
{
// Text was pasted into text box
}
_lastPosition = SelectionStart;
I went under the assumption that if more then 2 characters were entered into the text box at a time, then text must have been pasted, because how else can someone input more then 2 characters at a time? So anyway, this worked for me. Thanks to everyone who tried to help.
How can i check a value is pasted in Textbox?
As for as I understand you said that you have already use TextBox Keypress event and now you want to check if a value is pasted in TextBox or not
If you are pasting your value thorough mouse than may be this will work fine
Private Sub TextBox_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TextBox.MouseDown
If e.Button = Windows.Forms.MouseButtons.Right Then
//Code here what you want to do
End If
End Sub
Note this will help you if you are pasting your value through mouse right click
How to detect multiline paste in RichTextBox
Naïve detection
First solution you may think about is 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.
Detecting keyboard events (you have to override the OnKeyDown
function) and checking if the key combinations (CTRL+V and SHIFT+INS) is the one to paste text you may solve this.
Protected Sub OnKeyDown(ByVal e As KeyEventArgs)
Dim ctrlV As Boolean = e.Modifiers = Keys.Control && e.KeyCode = Keys.V
Dim shiftIns As Boolean = e.Modifiers = Keys.Shift && e.KeyCode = Keys.Insert
If ctrlV Or shiftIns Then
ProcessAllLines
End If
End Sub
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 (this isn't always true because of Unicode surrogates but it's not a problem in this case).
It doesn't work well with every IME (I didn't try with far east languages, for example) and with Unicode surrogates but for western languages it's OK (anyway even when it doesn't work you'll simply reprocess all lines). Also read this post and this post for more details about Unicode and this (twin) answer for C# version.
Dim _previousLength As Int32 = 0
Protected Sub richTextBox_TextChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim currentLength As Int32 = richTextBox.Text.Length
If Math.Abs(currentLength - _previousLength) > 1 Then
ProcessAllLines
End If
_previousLength = currentLength
End Sub
Perfect solution
The perfect solution of course exists (on Windows 8 or higher), the native rich edit control sends a 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 link on MSDN for details: http://msdn.microsoft.com/en-us/library/windows/desktop/hh768385(v=vs.85).aspx.
WPF handling text, image and file pasting event
You could handle the ApplicationCommands.Paste
command something like this to get the pasted in text, file(s) or image:
private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
if (e.Command == ApplicationCommands.Paste)
{
var files = Clipboard.GetFileDropList();
var text = Clipboard.GetData(DataFormats.Text);
var image = Clipboard.GetImage();
e.Handled = true;
}
}
JQuery - Paste event, stripping rich text
You could achieve something like this without needing a textarea
, just processing the code in the content editable div
every time that there is a change in its value, and removing all the tags but the paragraphs and line breaks.
The idea would be that every time that the content changes in the div (listen to the input
event):
- Replace in the inner HTML all
</p>
and<br>
for non-HTML tokens (e.g.:[p]
and[br]
respectively). - Remove all HTML tags (you can do it with
.text()
) - Replace the tokens that you used for their equivalents (and their openings!)
- Wrap everything between
<p>
and</p>
.
Here a simple demo:
$("#editable").on("input", function() {
$this = $(this);
// replace all br and closing p tags with special tokens $this.html($this.html().replace(/\<\/p\>/g,"[p]").replace(/\<br\>/g,"[br]"));
// remove all the tags, and then replace the tokens for their original values $this.html("<p>" + $this.text().replace(/\[p\]/g, "</p><p>").replace(/\[br\]/g,"<br>") + "</p>");
});
div#editable, div#demo { border:1px solid gray; padding:6px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div contenteditable="true" id="editable"></div>
<h3>Demo</h3><p>Copy this code and paste it on the editable div above:</p><div id="demo"> <p>This <b>is</b> <i>a</i> styled paragraph.</p> <p> </p> <p>The <span style="font-weight:bold">above paragraph</span> is empty.</p> <p>And this is a new paragraph…<br>with a line break!</p></div>
How can I pass make the text of a rich text box into a pre-defined variable in c#.net?
I needed to put all three lines into the same area. Thank you very much Igal!
Related Topics
How to Create a Generic Class from a String in C#
Exclude a Field/Property from the Database with Entity Framework 4 & Code-First
C# Property and Ref Parameter, Why No Sugar
Why Can't I Do Foreach (Var Item in Datatable.Rows)
The Operation Cannot Be Completed Because the Dbcontext Has Been Disposed Using MVC 4
C#: How to Edit Items and Subitems in a Listview
Webclient Does Not Support Concurrent I/O Operations
Is an Int a 64-Bit Integer in 64-Bit C#
Alternative to Findmimefromdata Method in Urlmon.Dll One Which Has More Mime Types
No Itemchecked Event in a Checkedlistbox
Multiple Fields Validation Using Remote Validation
Wpf: the Name Does Not Exist in the Namespace
How to Draw a Rounded Rectangle with Winforms (.Net)
Capture Screen on Server Desktop Session
Cannot Deserialize JSON Array into Type - JSON.Net