286

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

4

8 回答 8

372

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

于 2009-05-22T18:42:22.147 回答
160

System.Windows.Forms.Clipboard.SetText(Windows 窗体) 或System.Windows.Clipboard.SetText(WPF)

于 2009-05-22T18:41:31.477 回答
68

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

@Stecy:这是我们的集中式代码:

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();
}

然后我们有一个用于在剪贴板上设置文本的特定类。DataObject在某些版本的 Windows/.NET 上,在某些边缘情况下需要手动创建。我现在不记得确切的场景,.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();
于 2009-05-22T19:09:10.737 回答
24

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

窗体:System.Windows.Forms.Clipboard

两者都有一个静态SetText方法。

于 2009-05-22T18:41:21.150 回答
18

这对我有用:

你想做:

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(),字符串被复制到剪贴板,因此您可以粘贴或Ctrl+并将字符串作为要复制到剪贴板V的字符串取回。

于 2012-12-20T17:11:01.327 回答
15

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

在进行 OLE 调用之前,必须将当前线程设置为单线程单元 (STA) 模式

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

[STAThread]

static void Main(string[] args)
于 2012-05-02T09:07:28.110 回答
8

在 Windows 窗体中,如果您的字符串在文本框中,您可以轻松使用:

textBoxcsharp.SelectAll();
textBoxcsharp.Copy();
textBoxcsharp.DeselectAll();
于 2009-09-11T07:56:18.727 回答
-2

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

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

End Try

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

于 2015-09-18T08:34:07.843 回答