检测富文本框内是否发生粘贴事件
有没有办法可以找出富文本框中是否发生剪贴板粘贴事件? 此事件将用于使用粘贴的文本块执行某些操作。
谢谢
这是我的代码
protected override void WndProc(ref System.Windows.Forms.Message m) { if (m.Msg == WM_PASTE) { OnPasteOccurred(); MessageBox.Show("Pas"); } if (m.Msg == 0x000F) { if (PaintControl) { base.WndProc(ref m); } else { m.Result = IntPtr.Zero; } } else { base.WndProc(ref m); } }
编辑
我希望基于粘贴事件做一些语法突出显示或缩进,这个特定的代码编辑器似乎非常有效。 我不知道它是怎么做的。 在这个特定方向需要帮助。 我很确定必须有一些原生的Win32代码或类似的东西可以截取。 我试过追踪键,鼠标事件并不漂亮。
在RichTextBox
检测粘贴操作有点棘手。
第一种解决方案可能是检测覆盖WndProc
的WM_PASTE
消息,但遗憾的是控件在执行粘贴操作时不会将该消息发送给自身。
天真的检测
要检测键盘事件可能有效(您必须覆盖OnKeyDown
函数),然后检查键组合( CTRL + V和SHIFT + INS )。 像这样的东西:
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(); }
它运行良好,但您无法捕获使用鼠标进行的粘贴操作(右键单击以打开上下文菜单)以及通过拖放操作进行的粘贴操作。 如果您不需要它们,您可以使用此解决方案(至少它简单明了)。
更好的检测
假设:当用户在RichTextBox
内键入时,每次插入一个字符。 你怎么用这个? 好吧,当您检测到更大的更改时,您检测到粘贴操作,因为用户每次不能输入多于一次的字符(好吧,您可以说因为Unicode代理而不是总是如此)。 另请参阅VB.NET版本以及有关Unicode内容的更多详细信息 。
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; }
请注意,您不能(因为不同的IME工作)使用OnKeyDown
(或类似)。 这种方法仅适用于西方语言,但它存在Unicode内容的问题(因为,例如,当用户键入单个Char
时, String.Length
属性可能会增加两个Char
。有关此内容的更多详细信息,请参阅此post (好吧)一个强烈建议的阅读甚至,即使 – 在这种情况下 – 你不关心它。)在那篇文章中你还会找到一个更好的算法来确定字符串长度的代码。简而言之,你必须替换:
int currentLength = richTextBox.Text.Length;
有了这个:
int currentLength = StringInfo.GetTextElementEnumerator(richTextBox.Text) .Cast() .Count();
经过所有这些努力,您可能会意识到……用户甚至可以粘贴单个字符,但可能无法检测到。 你是对的,这就是为什么这是一个更好的检测而不是一个完美的解决方案 。
完美解决方案
当然存在完美的解决方案(如果您在Windows 8上运行),本机丰富的编辑控件会发送EN_CLIPFORMAT
通知消息。 它旨在通知富编辑控件的父窗口,使用特定的剪贴板格式粘贴。 然后,您可以覆盖其父级的WndProc
,以检测此通知的WM_NOTIFY
消息。 无论如何,这不是几行代码,请查看此MSDN文章了解详细信息。
从.Net 3.0开始,有一种内置的方法来检测粘贴事件:
DataObject.AddPastingHandler(this, OnPaste);
只需在构造函数中调用此方法即可。 例如,如果您想要自己处理粘贴事件,就像用户手动输入文本一样,您可以使用
private void OnPaste(object sender, DataObjectPastingEventArgs e) { if (e.DataObject.GetDataPresent(typeof(string))) { var text = (string)e.DataObject.GetData(typeof(string)); var composition = new TextComposition(InputManager.Current, this, text); TextCompositionManager.StartComposition(composition); } e.CancelCommand(); }