c# .net clipboard

¿Cómo copio el contenido de una cadena al portapapeles en C#?



.net clipboard (9)

Si tengo texto en una cadena, ¿cómo puedo copiarlo en el portapapeles para que el usuario pueda pegarlo en otra ventana (por ejemplo, de mi aplicación al Bloc de notas)?


Desearía que SetText fuera así de fácil, pero hay algunas trampas con las que tiene que lidiar. Debe asegurarse de que el subproceso en el que lo llama se esté ejecutando en la STA. A veces puede fallar con un error de acceso denegado y luego trabajar segundos después sin problemas, algo que ver con los problemas de tiempo de COM en el portapapeles. Y si se accede a su aplicación a través del escritorio remoto, el acceso al portapapeles es incompleto. Utilizamos un método centralizado para manejar todos los escenarios de tesis en lugar de llamar a SetText directamente.

@Stecy: Aquí está nuestro código centralizado:

La clase StaHelper simplemente ejecuta un código arbitrario en un hilo en el Single Thread Apartment (STA), requerido por el portapapeles.

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

Luego tenemos una clase específica para configurar texto en el portapapeles. La creación de un DataObject manualmente es necesaria en algunos casos DataObject en algunas versiones de Windows / .NET. No recuerdo los escenarios exactos ahora y puede que no sea necesario en .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 ); } }

El uso se ve así:

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


En Windows Forms, si su cadena está en un cuadro de texto, puede usar esto fácilmente:

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


Esto funciona para mí:

Quieres hacer:

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

Pero causa un error que dice que debe estar en un solo hilo de ApartmentState.STA.

Así que vamos a hacer que se ejecute en tal hilo. El código para ello:

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

Después de llamar a copy_to_clipboard() , la cadena se copia en el portapapeles, por lo que puede Pegar o Ctrl + V y recuperar la cadena como Cadena para copiar al portapapeles .


Usando la solución mostrada en esta pregunta, System.Windows.Forms.Clipboard.SetText(...) , produce la excepción:

El subproceso actual debe establecerse en el modo de apartamento de un solo subproceso (STA) antes de que se puedan realizar llamadas OLE

Para evitar esto, puede agregar el atributo:

[STAThread]

a

static void Main(string[] args)


Utilice try - catch , incluso si tiene un error, todavía se copiará.

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

Si usa un cuadro de mensaje para capturar la excepción, le mostrará un error, pero el valor aún se copia en el portapapeles.


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

Winforms: System.Windows.Forms.Clipboard

Ambos tienen un método SetText estático.




Puede usar System.Windows.Forms.Clipboard.SetText(...) .