我如何复制一个字符串的内容到剪贴板在c# ?

如果我在字符串中有一些文本,我如何将其复制到剪贴板,以便用户可以将其粘贴到另一个窗口(例如,从我的应用程序到记事本)?

204943 次浏览

WPF: System.Windows.Clipboard (PresentationCore.dll)

Winforms: System.Windows.Forms.Clipboard

它们都有一个静态的SetText方法。

你可以使用System.Windows.Forms.Clipboard.SetText(...)

我希望调用SetText是那么容易,但有相当多的陷阱,你必须处理。您必须确保调用它的线程正在STA中运行。它有时会因为拒绝访问错误而失败,然后在几秒钟后正常工作——这与剪贴板中的COM计时问题有关。如果您的应用程序是通过远程桌面访问剪贴板是粗略的。我们使用一个集中的方法来处理所有这些场景,而不是直接调用SetText

以下是我们的集中代码:

StaHelper类只是在单线程单元(STA)中的线程上执行一些任意代码——这是剪贴板所需要的。

abstract class StaHelper
{
readonly ManualResetEvent _complete = new ManualResetEvent( false );


public void Go()
{
var thread = new Thread( new ThreadStart( DoWork ) )
{
IsBackground = true,
}
thread.SetApartmentState( ApartmentState.STA );
thread.Start();
}


// Thread entry method
private void DoWork()
{
try
{
_complete.Reset();
Work();
}
catch( Exception ex )
{
if( DontRetryWorkOnFailed )
throw;
else
{
try
{
Thread.Sleep( 1000 );
Work();
}
catch
{
// ex from first exception
LogAndShowMessage( ex );
}
}
}
finally
{
_complete.Set();
}
}


public bool DontRetryWorkOnFailed{ get; set; }


// Implemented in base class to do actual work.
protected abstract void Work();
}

然后我们有一个特定的类来设置剪贴板上的文本。在某些Windows/. net版本的某些边缘情况下,手动创建DataObject是必需的。我现在不记得具体的场景了,在。net 3.5中可能不需要它。

class SetClipboardHelper : StaHelper
{
readonly string _format;
readonly object _data;


public SetClipboardHelper( string format, object data )
{
_format = format;
_data = data;
}


protected override void Work()
{
var obj = new System.Windows.Forms.DataObject(
_format,
_data
);


Clipboard.SetDataObject( obj, true );
}
}

用法如下:

new SetClipboardHelper( DataFormats.Text, "See, I'm on the clipboard" ).Go();

在Windows窗体中,如果你的字符串在文本框中,你可以很容易地使用这个:

textBoxcsharp.SelectAll();
textBoxcsharp.Copy();
textBoxcsharp.DeselectAll();

使用这个问题中显示的解决方案System.Windows.Forms.Clipboard.SetText(...)会导致异常:

在OLE调用之前,当前线程必须设置为单线程公寓(STA)模式

为了防止这种情况,你可以添加属性:

[STAThread]

static void Main(string[] args)

这对我来说很管用:

你想做的是:

System.Windows.Forms.Clipboard.SetText("String to be copied to Clipboard");

但是它会导致一个错误,说它必须在ApartmentState.STA的单个线程中。

让我们让它在这样一个线程中运行。它的代码:

public void somethingToRunInThread()
{
System.Windows.Forms.Clipboard.SetText("String to be copied to Clipboard");
}


protected void copy_to_clipboard()
{
Thread clipboardThread = new Thread(somethingToRunInThread);
clipboardThread.SetApartmentState(ApartmentState.STA);
clipboardThread.IsBackground = false;
clipboardThread.Start();
}

在调用copy_to_clipboard()之后,字符串被复制到剪贴板中,所以你可以Paste或Ctrl + V,并将字符串返回为要复制到剪贴板的字符串

使用try-catch,即使它有一个错误,它仍然会复制。

Try
Clipboard.SetText("copy me to clipboard")
Catch ex As Exception


End Try

如果使用消息框捕获异常,它将显示错误,但值仍然复制到剪贴板。