Как мне скопировать содержимое строки в буфер обмена в C #? - PullRequest
250 голосов
/ 22 мая 2009

Если у меня есть какой-то текст в строке, как я могу скопировать его в буфер обмена, чтобы пользователь мог вставить его в другое окно (например, из моего приложения в блокнот)?

Ответы [ 8 ]

315 голосов
/ 22 мая 2009

Вы можете использовать System.Windows.Forms.Clipboard.SetText(...).

129 голосов
/ 22 мая 2009
64 голосов
/ 22 мая 2009

Хотелось бы, чтобы звонить 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();
22 голосов
/ 22 мая 2009

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

Винформ: System.Windows.Forms.Clipboard

Оба имеют статический SetText метод.

16 голосов
/ 20 декабря 2012

Это работает для меня:

Вы хотите сделать:

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 и получить строку как String для копирования в буфер обмена .

13 голосов
/ 02 мая 2012

Использование решения, показанного в этом вопросе, System.Windows.Forms.Clipboard.SetText(...), приводит к исключению:

Для выполнения OLE-вызовов текущий поток должен быть переведен в однопотоковый режим (STA)

Чтобы предотвратить это, вы можете добавить атрибут:

[STAThread]

до

static void Main(string[] args)
7 голосов
/ 11 сентября 2009

В Windows Forms, если ваша строка находится в текстовом поле, вы можете легко использовать это:

textBoxcsharp.SelectAll();
textBoxcsharp.Copy();
textBoxcsharp.DeselectAll();
0 голосов
/ 18 сентября 2015

Используйте try - catch, даже если возникнет ошибка, она все равно будет скопирована.

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

End Try

Если вы используете окно сообщения для захвата исключения, оно покажет вам ошибку, но значение все равно будет скопировано в буфер обмена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...