Как мне скопировать содержимое строки в буфер обмена в C#?
Если у меня есть какой-то текст в строке, как я могу скопировать его в буфер обмена, чтобы пользователь мог вставить его в другое окно (например, из моего приложения в блокнот)?
8 ответов
Ты можешь использовать System.Windows.Forms.Clipboard.SetText(...)
,
System.Windows.Forms.Clipboard.SetText
(Winforms) или System.Windows.Clipboard.SetText
(WPF)
Я желаю звонить SetText
Было бы так просто, но есть немало ошибок, с которыми вам приходится иметь дело. Вы должны убедиться, что поток, к которому вы его вызываете, работает в STA. Иногда он может завершиться с ошибкой отказа в доступе, а затем работать без проблем через несколько секунд - что-то связанное с проблемами синхронизации COM в буфере обмена. И если к вашему приложению обращаются через удаленный рабочий стол, доступ к буферу обмена оказывается поверхностным. Мы используем централизованный метод для обработки всех этих сценариев вместо вызова SetText
непосредственно.
@ Stecy: Вот наш централизованный код:
Класс StaHelper просто выполняет некоторый произвольный код в потоке в Single Thread Apartment (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();
WPF: System.Windows.Clipboard
(PresentationCore.dll)
Winforms: System.Windows.Forms.Clipboard
У обоих есть статика SetText
метод.
Это работает для меня:
Ты хочешь сделать:
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 и вернуть строку как строку для копирования в буфер обмена.
Используя решение, показанное в этом вопросе, System.Windows.Forms.Clipboard.SetText(...)
, приводит к исключению:
Текущий поток должен быть установлен в однопотоковый режим (STA), прежде чем можно будет выполнять вызовы OLE
Чтобы предотвратить это, вы можете добавить атрибут:
[STAThread]
в
static void Main(string[] args)
В Windows Forms, если ваша строка находится в текстовом поле, вы можете легко использовать это:
textBoxcsharp.SelectAll();
textBoxcsharp.Copy();
textBoxcsharp.DeselectAll();
Использование try
-catch
, даже если он имеет ошибку, он все равно будет копировать.
Try
Clipboard.SetText("copy me to clipboard")
Catch ex As Exception
End Try
Если вы используете окно сообщения для захвата исключения, оно покажет вам ошибку, но значение все равно будет скопировано в буфер обмена.