WPF RichTextBox - Remove text formatting on paste and move caret properly - c#

I am having trouble removing the formatting (bold, font, size etc.) on paste of some formatted text into a RichTextBox.
I have successfully been using the following:
Add a pasting handler to the RichTextBox
DataObject.AddPastingHandler(RichTextBoxControl, TextBoxPasting);
Remove formatting and insert text
private void TextBoxPasting(object sender, DataObjectPastingEventArgs e)
{
var pastingText = e.DataObject.GetData(DataFormats.Text) as string;
RichTextBoxControl.Document.ContentEnd.InsertTextInRun(pastingText);
e.CancelCommand();
}
But unfortunately this always places the inserted text in the end of the RichTextBox. Also the caret is not moving.
Let us say you are at this positing:
Helloꕯ World and you are pasting Beautiful you would get Helloꕯ World Beutiful instead of Hello Beutifulꕯ World.

Instead of manually inserting the text and cancelling the event you could just alter the text that is to be inserted in the DataObjectPastingEventArgs, and let the chains of the event do all the work for you.
private static void TextBoxPasting(object sender, DataObjectPastingEventArgs e)
{
e.DataObject = new DataObject(DataFormats.Text, e.DataObject.GetData(DataFormats.Text) as string ?? string.Empty);
}
e.DataObject.GetData(DataFormats.Text) is getting you the plain text without any formatting. The caret will move properly since you are not canceling the events that were supposed to move it.

Related

How can I copy a line from a Richtextbox when I select it?

I am trying to automatically highlight and copy a single line from a rich text box and store it in a variable when I click on any part of the line.
Is this possible?
The Click event and something like the following should help:
private void richTextBox1_Click(object sender, EventArgs e)
{
int index = richTextBox1.SelectionStart;
int line = richTextBox1.GetLineFromCharIndex(index);
string lineText = (richTextBox1.Lines.Length > 0) ? richTextBox1.Lines[line] : "";
//Debug output for my own testing purposes
Debug.WriteLine(lineText);
}
You may want to do something different when the RichTextBox is empty. I just use an empty string.
Here's an example of the output from a simple app:
The text show in the output window reflects the order in which I clicked the lines after typing.
However, one caveat to this is that you don't need to click exactly on the line for it to count. For example, clicking in the empty space below the last line registers as clicking the last line, because that's where the cursor ends up. It might not matter a whole lot, but it's something to be aware of.

WPF - Copying the content of a RichTextBox into a Paragraph

I'm currently trying to create a simple program in WPF to make cards for a custom card game.
Some of the descriptions feature rich text (like bold and italics) to highlight important things. The effect and the flavor text are copied into the same RichTextBox for aesthetic and convenience, which is why I need to be able to copy rich text from an input into a line/paragraph that is added to the display.
Here is the code:
private void EffectInput_TextChanged(object sender, TextChangedEventArgs e)
{
TextRange temp = new TextRange(EffectInput.Document.ContentStart, EffectInput.Document.ContentEnd);
Console.WriteLine(temp.Text);
effectText.Inlines.Clear();
effectText.Inlines.Add(new Run(temp.Text));
updateDescription();
}
private void updateDescription()
{
Description.Document.Blocks.Clear();
Description.Document.Blocks.Add(effectText);
Description.Document.Blocks.Add(flavorText);
}
I managed to make it work with the Text inside the box, but I can't find a way to also copy the format of the text. Can anyone help me?

Set specific text to bold in WPF RichTextBox

I am extending the functionality of a WPF Richtextbox. I want certain text to become bold when I type it in. I was able to get certain text to bold but the text following the bolded word would also become bolded...
Heres a sample of my code:
private bool _Running = false;
void CustomRichTextBox_TextChange(object sender, TextChangedEventArgs e)
{
if(_Running)
return;
_Running = true;
//Logic to see if text detected
//Logic to get TextPointers
//Logic to get TextRange
var boldMe = new TextRange(textPointer1, textPointer2);
//Bold text
boldMe.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);
_Running = false;
}
I want:
NOTBOLDED NOTBOLDED BOLDED NOTBOLDED
but what I get:
NOTBOLDED NOTBOLDED BOLDED NOTBOLDED
**Please note that it becomes bolded while typing.
How do I prevent the text after a bolded word from also becoming bolded?
Not duplicate question since the accepted solution for provided link is for WinForms and the rest are for preset text.
After several tests, I figured out a simple solution.
CaretPosition = CaretPosition.GetPositionAtOffset(0, LogicalDirection.Forward);
This set caret in the right orientation, preventing the BOLD setting from continuing within the Run object.
if(textPointerEnd.GetNextInsertionPosition(LogicalDirection.Forward) == null)
new Run("", textPointerEnd);
This would add a Run object to the end of a new Bold object that was located at the end of the Paragraph object.
You will need to detect when your required text is no longer detected, probably if a space occurs, then remove the bolding value and reset it back to normal.

How to Paste text with images from clipboard like Microsoft Word do C#?

i was wondering how can i paste the content of my clipboard like Microsoft word do, i mean for example if i want to copy something like:
Some text
*some image*
More text
and paste it just like it was when i copied with the text and the image between the text, how can i do that?
I tried with Rich Textbox pasting with HTML Format but still got nothing...
So far i can only paste the text without format or the HTML text with the tags also without format...
By the way, is there some way to override the Ctrl + V paste method of a textbox?
Thank you
EDIT: I'm working on WinForms
If you can see the image displayed in RichTextBox via copy paste, then you can do the same from code as follow :
myRichTextBox.Rtf = Clipboard.GetText(TextDataFormat.Rtf);
simple step, set RichTextBox's Rtf property to value you get from Clipboard in Rtf format.
As to the first question, I don't believe you can do that with the RichTextBox. You can paste an image by itself, or you can paste just the text if you copied text and images from a website. But it won't paste both, unfortunately.
Here's a previous SO post where some suggestions were thrown out.
As for the other question, if you want to override CTRL+V functionality, you'll have to subscribe to the KeyDown and KeyPress events:
private bool IsPressedCtrlV = false;
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
// You have access to modifiers in here, so you can detect the Control key
IsPressedCtrlV = (e.Modifiers == Keys.Control && e.KeyCode == Keys.V);
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (IsPressedCtrlV)
{
// When the key "press" is complete, handle ctrl-v however you want
e.Handled = true;
MessageBox.Show("No pasting allowed!");
}
}

How can I prevent system clipboard image data being pasted into a WPF RichTextBox

I have some code in place currently to intercept all Cut, Copy and Paste events into a RichTextBox in WPF. These are designed to strip all content out except plain text, and allow no pasting except plain text (by using a check the Clipboard.ContainsText() method.) This seems to be successful at preventing all such operations from inside the forms. A user can only copy, cut and paste text around, with images / audio data / random junk not being allowed.
However, if I use the PrintScreen function, and paste it into one of the RichTextBoxes, the image is pasted in (not the wanted behaviour.) If you then try and paste this image from one RichTextBox to another though, it won't let you (the desired behaviour).
The commands I'm currently overriding are done using
// Command handlers for Cut, Copy and Paste commands.
// To enforce that data can be copied or pasted from the clipboard in text format only.
CommandManager.RegisterClassCommandBinding(typeof(MyRichTextBox),
new CommandBinding(ApplicationCommands.Copy, new ExecutedRoutedEventHandler(OnCopy),
new CanExecuteRoutedEventHandler(OnCanExecuteCopy)));
CommandManager.RegisterClassCommandBinding(typeof(MyRichTextBox),
new CommandBinding(ApplicationCommands.Paste, new ExecutedRoutedEventHandler(OnPaste),
new CanExecuteRoutedEventHandler(OnCanExecutePaste)));
CommandManager.RegisterClassCommandBinding(typeof(MyRichTextBox),
new CommandBinding(ApplicationCommands.Cut, new ExecutedRoutedEventHandler(OnCut),
new CanExecuteRoutedEventHandler(OnCanExecuteCut)));
The OnCopy (etc) methods then essentially check that only text is present before allowing any operations.
There seems to be two Clipboards at work here, one of which I'm not restricting / locking down. Does anyone know of the technicalities of this, and any way in which all Clipboard activity (both Form and System) can be locked down and customized effectively?
Thanks in advance.
It might be a bit unforgiving for the user but you could do it as simple as hijacking and clearing the Clipboard before pasting. Just hook the PreviewKeyDown (since on KeyUp it´s already been inserted) and clear the clipboard if we´ve got an image and is pressing Ctrl+V:
public Window1()
{
InitializeComponent();
_rtf.PreviewKeyDown += OnClearClipboard;
}
private void OnClearClipboard(object sender, KeyEventArgs keyEventArgs)
{
if (Clipboard.ContainsImage() && keyEventArgs.Key == Key.V && (Keyboard.Modifiers & ModifierKeys.Control) != 0)
Clipboard.Clear();
}
Not the neatest solution but it´ll do the trick.
Actually you dont need any hack like catching the KeyDown events (which wouldn't prevent pasting through the context menu or drag and drop anyway). There's a specific attached event for that: DataObject.Pasting.
XAML:
<RichTextBox DataObject.Pasting="RichTextBox1_Pasting" ... />
Code-behind:
private void RichTextBox1_Pasting(object sender, DataObjectPastingEventArgs e)
{
if (e.FormatToApply == "Bitmap")
{
e.CancelCommand();
}
}
It prevents all forms of pasting (Ctrl-V, right-click -> Paste, drag and drop).
If you want to be smarter than that, you can also replace the DataObject with one that contains only the formats you want to support (rather than completely cancelling the paste).
I think this is probably a better way if your goal is to just allow the plain text to be pasted:
private void richTextBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.V)
{
if (Clipboard.GetData("Text") != null)
Clipboard.SetText((string)Clipboard.GetData("Text"), TextDataFormat.Text);
else
e.Handled = true;
}
}

Categories