Open GeneThomas opened 4 years ago
My fix for this one is to override Ctrl.V and paste the text myself but keeping the scroll position and caret the same is awkward:
// this is a derrived class from Eto.Forms.TextArea
using ewf = Eto.WinForms;
using swf = System.Windows.Forms;
void HandlePaste(object sender, KeyEventArgs e)
{
try
{
e.Handled = true;
// always handle otherwise the origional Ctrl.V handler will be called
string text = Clipboard.Instance.Text;
if (text == null)
return;
if (Selection.Start <= Selection.End)
{
GtAssert.AreEqual(Selection.Start, CaretIndex);
ewfc.TextAreaHandler handler = (ewfc.TextAreaHandler)Handler;
swf.TextBoxBase SwfTextbox = handler.Control;
ReplaceText(SwfTextbox, Selection.Start, Selection.End - Selection.Start + 1, text, isInsert: true);
}
else
{
Insert(text);
}
}
catch (Exception ex)
{
Trace.TraceError($"HandlePaste exception: {ex.GetCompleteMessage()}");
}
}
public void Insert(string toinsert)
{
ewfc.TextAreaHandler handler = (ewfc.TextAreaHandler)Handler;
swf.TextBoxBase SwfTextbox = handler.Control;
if (SwfTextbox.SelectionLength == 0)
{
ReplaceText(SwfTextbox, CaretIndex, 0, toinsert, isInsert: true);
}
else
{
ReplaceText(SwfTextbox, SwfTextbox.SelectionStart, SwfTextbox.SelectionLength, toinsert, isInsert: true);
}
}
/// <summary>
/// remove and/or insert without flcikers nor scroll bar jumping
/// </summary>
public static void ReplaceText(swf.TextBoxBase swfTextbox, int offset, int length, string insert, bool isInsert)
{
Win32.LockWindowUpdate(swfTextbox.Handle);
// using .Visible does not remove all flicker
try
{
int startIndex = swfTextbox.GetCharIndexFromPosition(new sd.Point(0, 0));
int caret = swfTextbox.SelectionStart;
string text = swfTextbox.Text;
if (length != 0)
{
text = swfTextbox.Text.Remove(offset, length);
}
if (insert != "")
{
text = text.Insert(offset, insert);
}
swfTextbox.Text = text;
// puts caret at end
swfTextbox.SelectionStart = text.Length;
swfTextbox.ScrollToCaret();
if (startIndex >= text.Length || text[startIndex] == '\n')
{
swfTextbox.SelectionStart = startIndex;
}
else
{
swfTextbox.SelectionStart = startIndex + 1;
// winforms gets this wrong and scrolls to the
// line above if set to 'startIndex'
}
swfTextbox.ScrollToCaret();
// set scroll bar back
if (isInsert)
{
if (caret <= offset)
{
// both insert char and replace selection with char
swfTextbox.SelectionStart = caret + insert.Length;
return;
}
// may be impossible
if (caret < offset + length)
{
int dist = (offset + length) - caret;
swfTextbox.SelectionStart = caret + insert.Length;
return;
}
swfTextbox.SelectionStart = caret - length + insert.Length;
return;
}
if (caret <= offset)
{
swfTextbox.SelectionStart = caret;
return;
}
if (caret > offset + insert.Length)
{
// long word replaced with smaller
// would end up after repalcement word
swfTextbox.SelectionStart = offset + insert.Length;
return;
}
if (caret < offset + length)
{
swfTextbox.SelectionStart = caret;// + dist;// + replacement.Length;
return;
}
// may never happen
swfTextbox.SelectionStart = caret - length + insert.Length;
}
catch (Exception e)
{
Trace.TraceError($"Exception in GtTextArea.ReplaceText(): {e.GetCompleteMessage()}");
}
finally
{
Win32.LockWindowUpdate(IntPtr.Zero);
}
}
Ctrl.C copy and Ctrl.X cut also break as they put RTF and text in the clipboard, so pasting into Wordpad breaks. e.g. if you have some-text-in-bold and paste the text copied from a TextArea the pasted text has the font of the TextArea, not adopting the bold as happens when text is copied from notepad.
fix:
/// <summary>
/// the default behavior is to put markup in the text
/// so pasting into wordpad breaks
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void HandleCopy(object sender, KeyEventArgs e)
{
try
{
e.Handled = true;
// always handle otherwise the origional Ctrl.C handler will be called
if (Selection.End >= Selection.Start)
{
// has selection
string text = Text.SafeSubstring(Selection.Start, Selection.End - Selection.Start + 1);
ClipboardExtensions.SetClipboardText(text);
}
else
{
// no selection
}
}
catch (Exception ex)
{
Trace.TraceError($"HandleCopy exception: {ex.GetCompleteMessage()}");
}
}
void HandleCut(object sender, KeyEventArgs e)
{
try
{
e.Handled = true;
// always handle otherwise the origional Ctrl.C handler will be called
if (Selection.End >= Selection.Start)
{
// has selection
ewfc.TextAreaHandler handler = (ewfc.TextAreaHandler)Handler;
swf.TextBoxBase SwfTextbox = handler.Control;
string text = Text.SafeSubstring(Selection.Start, Selection.End - Selection.Start + 1);
ClipboardExtensions.SetClipboardText(text);
ReplaceText(SwfTextbox, Selection.Start, Selection.End - Selection.Start + 1, "", isInsert: false);
}
else
{
// no selection
}
}
catch (Exception ex)
{
Trace.TraceError($"HandleCut exception: {ex.GetCompleteMessage()}");
}
}
Expected Behavior
All text in the TextArea should be the same font I am wondering why Eto.Forms on WinForms uses a sub-class of System.Windows.Forms.RichTextBox to implement TextArea? TextArea is not supposed to have markup.
Actual Behavior
Pasted RTF has bold markup show in TextArea![screenshot](https://user-images.githubusercontent.com/514360/75642666-2c3e6c80-5ca1-11ea-865b-18464da83630.png)
Steps to Reproduce the Problem
Code that Demonstrates the Problem
EtoFormsFault-TextAreaPaste.zip
Specifications