Я использую объект Rich Text в своем приложении С#. Единственная проблема, с которой я сталкиваюсь, заключается в том, что когда пользователь вставляет отформатированный текст из другого приложения, он остается отформатированным, чего у меня не может быть. Есть ли способ вставить только строку и игнорировать форматирование? Спасибо!
c# RTB - вставить обычный текст без цветов/шрифтов?
Ответы (10)
Предполагая WinForms: попробуйте следующее: определите RichTextBox с обработчиком событий KeyDown следующим образом:
Пример только для добавления:
private void richTextBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.V)
{
richTextBox1.Text += (string)Clipboard.GetData("Text");
e.Handled = true;
}
}
[Редактировать]
Пример добавления буфера обмена RTF в RichTextBox в текущей точке вставки (начало выделения):
private void richTextBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.V)
{
// suspend layout to avoid blinking
richTextBox2.SuspendLayout();
// get insertion point
int insPt = richTextBox2.SelectionStart;
// preserve text from after insertion pont to end of RTF content
string postRTFContent = richTextBox2.Text.Substring(insPt);
// remove the content after the insertion point
richTextBox2.Text = richTextBox2.Text.Substring(0, insPt);
// add the clipboard content and then the preserved postRTF content
richTextBox2.Text += (string)Clipboard.GetData("Text") + postRTFContent;
// adjust the insertion point to just after the inserted text
richTextBox2.SelectionStart = richTextBox2.TextLength - postRTFContent.Length;
// restore layout
richTextBox2.ResumeLayout();
// cancel the paste
e.Handled = true;
}
}
[Конец редактирования]
Примечание 0. Вставленный текст будет предполагать текущие настройки стиля, действующие для RichTextBox: если для параметра «Цвет переднего плана» установлено значение «Синий»: вставленный текст будет синим.
Примечание 1: Это то, что я быстро собрал и протестировал всего несколько раз, создав несколько разноцветных и странно отформатированных RTF для буфера обмена с помощью WordPad: затем вставив в RichTextBox1 во время выполнения: он удалил все цвет, отступ и т.д.
Поскольку он не полностью протестирован, соблюдайте осторожность.
Примечание 2. Очевидно, что это не будет обрабатывать случай «Вставить» или «Вставить через контекстное меню».
Приветствую всю критику этого ответа и немедленно уберу его, если он не «на высоте».
richTextBox2.Text.Substring(insPt + richTextBox2.SelectionLength), чтобы выделенный текст заменялся при вставке, как и должно быть. Кроме того, устаревшее сочетание клавиш Shift+Insert также должно быть добавлено в качестве комбинации клавиш.
- person Nyerguds; 17.02.2016
SuspendLayout(), изменение текста все равно обновит элемент управления. Лучший способ предотвратить это — внести как можно меньше изменений в свойство Text, сначала составив строку, а затем просто назначив ее один раз.
- person Nyerguds; 17.02.2016
Добавьте обработчик к событию KeyDown, чтобы перехватывать стандартную вставку и вручную вставлять только обычный текст:
private void rtb_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.V)
{
((RichTextBox)sender).Paste(DataFormats.GetFormat("Text"));
e.Handled = true;
}
}
Я искал richtextbox только для открытого текста, но не нашел решения в Интернете.
Почему только открытый текст RichTextBox вместо TextBox? Например, потому что RichTextBox имеет полезные функции отмены/возврата и многое другое.
Наконец, я нашел идеальное решение, покопавшись в заголовочных файлах C элемента управления richedit: RichTextBox можно переключить в режим обычного текста, после чего он не принимает форматированный текст, изображения и подобные вещи из буфера обмена и ведет себя как обычный TextBox форматирование. Необычные вещи, такие как изображения, не могут быть вставлены, и он вставляет форматированный текст, удаляя форматирование.
class PlainRichTextBox : RichTextBox
{
const int WM_USER = 0x400;
const int EM_SETTEXTMODE = WM_USER + 89;
const int EM_GETTEXTMODE = WM_USER + 90;
// EM_SETTEXTMODE/EM_GETTEXTMODE flags
const int TM_PLAINTEXT = 1;
const int TM_RICHTEXT = 2; // Default behavior
const int TM_SINGLELEVELUNDO = 4;
const int TM_MULTILEVELUNDO = 8; // Default behavior
const int TM_SINGLECODEPAGE = 16;
const int TM_MULTICODEPAGE = 32; // Default behavior
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
bool m_PlainTextMode;
// If this property doesn't work for you from the designer for some reason
// (for example framework version...) then set this property from outside
// the designer then uncomment the Browsable and DesignerSerializationVisibility
// attributes and set the Property from your component initializer code
// that runs after the designer's code.
[DefaultValue(false)]
//[Browsable(false)]
//[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool PlainTextMode
{
get
{
return m_PlainTextMode;
}
set
{
m_PlainTextMode = value;
if (IsHandleCreated)
{
IntPtr mode = value ? (IntPtr)TM_PLAINTEXT : (IntPtr)TM_RICHTEXT;
SendMessage(Handle, EM_SETTEXTMODE, mode, IntPtr.Zero);
}
}
}
protected override void OnHandleCreated(EventArgs e)
{
// For some reason it worked for me only if I manipulated the created
// handle before calling the base method.
PlainTextMode = m_PlainTextMode;
base.OnHandleCreated(e);
}
}
Ответ от pasztorpisti сработал для меня как шарм. Поскольку я использую vb.net, я решил опубликовать свой переведенный код для других:
Imports System.Runtime.InteropServices
Imports System.ComponentModel
Public Class MyRichTextBox
Inherits Windows.Forms.RichTextBox
Public Const WM_USER As Integer = &H400
Public Const EM_SETTEXTMODE As Integer = WM_USER + 89
Public Const EM_GETTEXTMODE As Integer = WM_USER + 90
'EM_SETTEXTMODE/EM_GETTEXTMODE flags
Public Const TM_PLAINTEXT As Integer = 1
Public Const TM_RICHTEXT As Integer = 2 ' Default behavior
Public Const TM_SINGLELEVELUNDO As Integer = 4
Public Const TM_MULTILEVELUNDO As Integer = 8 ' Default behavior
Public Const TM_SINGLECODEPAGE As Integer = 16
Public Const TM_MULTICODEPAGE As Integer = 32 ' Default behavior
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
End Function
Private _plainTextMode As Boolean = False
<DefaultValue(False),
Browsable(True)>
Public Property PlainTextMode As Boolean
Get
Return _plainTextMode
End Get
Set(value As Boolean)
_plainTextMode = value
If (Me.IsHandleCreated) Then
Dim mode As IntPtr = If(value, TM_PLAINTEXT, TM_RICHTEXT)
SendMessage(Handle, EM_SETTEXTMODE, mode, IntPtr.Zero)
End If
End Set
End Property
Protected Overrides Sub OnHandleCreated(e As EventArgs)
'For some reason it worked for me only if I manipulated the created
'handle before calling the base method.
Me.PlainTextMode = _plainTextMode
MyBase.OnHandleCreated(e)
End Sub
End Class
Что ж, RichTextBox имеет свойство SelectionFont, поэтому вы можете, например, сделать следующее:
Font courier;
courier = new Font("Courier new", 10f, FontStyle.Regular);
myRtb.SelectionFont = courier;
myRtb.Font = courier; //So the typed text is also the same font
Если текст будет вставлен, он будет автоматически отформатирован.
Вы также можете использовать
private void richTextBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.V)
{
richTextBox1.SelectedText = (string)Clipboard.GetData("Text");
e.Handled = true;
}
}
Я добился этого, обновив шрифт и цвет для всего RTB при изменении его содержимого. Это отлично работает для меня, так как поле ввода не должно иметь дело с огромным количеством текста.
public FormMain()
{
InitializeComponent();
txtRtb.TextChanged += txtRtb_TextChanged;
}
void txtRtb_TextChanged(object sender, EventArgs e)
{
RichTextBox rtb = (RichTextBox)sender;
rtb.SelectAll();
rtb.SelectionFont = rtb.Font;
rtb.SelectionColor = System.Drawing.SystemColors.WindowText;
rtb.Select(rtb.TextLength,0);
}
Мое решение
private void OnCommandExecuting(object sender, Telerik.Windows.Documents.RichTextBoxCommands.CommandExecutingEventArgs e)
{
if (e.Command is PasteCommand)
{
//override paste when clipboard comes from out of RichTextBox (plain text)
var documentFromClipboard = ClipboardEx.GetDocumentFromClipboard("RadDocumentGUID");
if (documentFromClipboard == null)
{
(sender as RichTextBox).Insert(Clipboard.GetText());
e.Cancel = true;
}
}
}
Есть очень простой способ сделать это, который хорошо работает для меня:
private bool updatingText;
public MyForm() {
InitializeComponent();
inputTextBox.TextChanged += inputTextBox_TextChanged;
}
private void inputTextBox_TextChanged(object sender, EventArgs e)
{
if (updatingText)
{
return;
}
updatingText = true;
try
{
var i = inputTextBox.SelectionStart;
var text = inputTextBox.Text;
inputTextBox.Rtf = "";
inputTextBox.Text = text;
inputTextBox.SelectionStart = i;
}
catch (Exception){}
updatingText = false;
}
Поскольку свойство Text по своей сути не форматирует сброс текста RTF, установка свойства text на необработанный ввод удаляет любые специальные элементы, которые могли быть вставлены.
Просто, но все в буфере обмена находится в виде обычного текста, когда приложение открыто.
private void timer2_Tick(object sender, EventArgs e)
{
string paste = Clipboard.GetText();
Clipboard.SetText(paste);
}