【发布时间】:2011-03-27 15:36:36
【问题描述】:
我需要“修改”所有粘贴到 TextBox 中的文本,以便以某种结构化的方式显示。我可以使用拖放、ctrl-v 来完成,但如何使用默认上下文的菜单“粘贴”来完成?
【问题讨论】:
我需要“修改”所有粘贴到 TextBox 中的文本,以便以某种结构化的方式显示。我可以使用拖放、ctrl-v 来完成,但如何使用默认上下文的菜单“粘贴”来完成?
【问题讨论】:
虽然我通常不建议使用低级别的 Windows API,而且这可能不是这样做的唯一方法,但它确实可以解决问题:
using System;
using System.Windows.Forms;
public class ClipboardEventArgs : EventArgs
{
public string ClipboardText { get; set; }
public ClipboardEventArgs(string clipboardText)
{
ClipboardText = clipboardText;
}
}
class MyTextBox : TextBox
{
public event EventHandler<ClipboardEventArgs> Pasted;
private const int WM_PASTE = 0x0302;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_PASTE)
{
var evt = Pasted;
if (evt != null)
{
evt(this, new ClipboardEventArgs(Clipboard.GetText()));
// don't let the base control handle the event again
return;
}
}
base.WndProc(ref m);
}
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var tb = new MyTextBox();
tb.Pasted += (sender, args) => MessageBox.Show("Pasted: " + args.ClipboardText);
var form = new Form();
form.Controls.Add(tb);
Application.Run(form);
}
}
最终,WinForms 工具包不是很好。它是 Win32 和 Common Controls 的精简包装器。它公开了 80% 的最有用的 API。另外 20% 经常丢失或没有以明显的方式暴露。如果可能的话,我建议从 WinForms 转移到 WPF,因为 WPF 似乎是一个更好的 .NET GUI 架构框架。
【讨论】:
if 语句中缺少return,这会导致基本控件重新处理此事件。我在粘贴时格式化 XML 并且没有 return,格式化和未格式化的 XML 都会显示为基本控件再次处理粘贴。
Pasted == null 和调用处理程序之间可能发生的竞争条件。如果单独的订阅者在检查和调用之间取消订阅另一个线程上的事件,您最终可能会遇到空引用异常。 C# 6 允许 Pasted?.Invoke() 作为替代的安全解决方案。
Pasted 事件在第一名。因此,即使我们进入 C#10,这个实现仍然是相关的。