2009-02-06 26 views
36

mio appunti è popolato con il testo, ma quando corroClipboard.GetText restituisce null (stringa vuota)

string clipboardData = Clipboard.GetText(System.Windows.Forms.TextDataFormat.Text); 

torno una stringa vuota. Ho giocato con varie forme della chiamata, tra cui:

string clipboardData = Clipboard.GetText(); 
string clipboardData = Clipboard.GetText(System.Windows.Forms.TextDataFormat.UnicodeText); 

Ma con lo stesso risultato.

Mi manca qualcosa di ovvio?

+0

Come si inseriscono i dati negli Appunti? –

+0

I dati presenti negli Appunti sono "testo" e non grafici, audio o altro? – JMD

risposta

45

È possibile accedere agli Appunti solo da un thread STA. Rick Brewster si è imbattuto in questo con alcuni refactoring del normale comando Modifica-> Incolla, in Paint.NET.

Codice:

IDataObject idat = null; 
Exception threadEx = null; 
Thread staThread = new Thread(
    delegate() 
    { 
     try 
     { 
      idat = Clipboard.GetDataObject(); 
     } 

     catch (Exception ex) 
     { 
      threadEx = ex;    
     } 
    }); 
staThread.SetApartmentState(ApartmentState.STA); 
staThread.Start(); 
staThread.Join(); 
// at this point either you have clipboard data or an exception 

Codice è da Rick. http://forums.getpaint.net/index.php?/topic/13712-/page__view__findpost__p__226140

Aggiornamento: Jason Heine fatto un buon punto di aggiungere () dopo delegate per correggere l'errore metodo di ambiguo.

+5

non sicuro su altri framework, ma in .net 4.0 delegate deve avere() dopo di esso, altrimenti si ottiene un errore di metodo ambiguo. – CodeLikeBeaker

+0

Dovremmo aggiungere qualche blocco? – Toto

+0

Buona risposta, anche se nel mio caso era solo che avevo un WinForms in cui avevo rimosso l'attributo [STAThread] su Main, quindi ho dovuto solo rimetterlo. –

0

Per qualche motivo il codice di BoltBait non ha funzionato (ID era ancora nullo anche dopo staThread.Join()). Ho appena fatto Clipboard.GetText() all'interno del delegato staThread invece di Clipboard.GetDataObject() e questo ha funzionato bene.

Grazie anche se - lo snippet di codice mi ha fatto il 99% ci :)

+0

Fantastico. Sono contento che tu abbia funzionato. – BoltBait

+0

Ciao Jonathan: ho visto esattamente la stessa cosa e ho fatto la stessa cosa. – Matt

9

ho scritto questa classe, funziona, e fare la stessa cosa e possono essere facilmente migliorati semplicemente aggiungendo il metodo che è necessario

Private Class ClipboardAsync 

    Private _GetText As String 
    Private Sub _thGetText(ByVal format As Object) 
     Try 
      If format Is Nothing Then 
       _GetText = Clipboard.GetText() 
      Else 
       _GetText = Clipboard.GetText(DirectCast(format, TextDataFormat)) 
      End If 

     Catch ex As Exception 
      _GetText = String.Empty 
     End Try 
    End Sub 
    Public Function GetText() As String 
     Dim instance As New ClipboardAsync 
     Dim staThread As New Thread(AddressOf instance._thGetText) 
     staThread.SetApartmentState(ApartmentState.STA) 
     staThread.Start() 
     staThread.Join() 
     Return instance._GetText 
    End Function 
    Public Function GetText(ByVal format As TextDataFormat) As String 
     Dim instance As New ClipboardAsync 
     Dim staThread As New Thread(AddressOf instance._thGetText) 
     staThread.SetApartmentState(ApartmentState.STA) 
     staThread.Start(format) 
     staThread.Join() 
     Return instance._GetText 
    End Function 

    Private _ContainsText As Boolean 
    Private Sub _thContainsText(ByVal format As Object) 
     Try 
      If format Is Nothing Then 
       _ContainsText = Clipboard.ContainsText() 
      Else 
       _ContainsText = Clipboard.ContainsText(DirectCast(format, TextDataFormat)) 
      End If 
     Catch ex As Exception 
      _ContainsText = False 
     End Try 
    End Sub 
    Public Function ContainsText() As Boolean 
     Dim instance As New ClipboardAsync 
     Dim staThread As New Thread(AddressOf instance._thContainsFileDropList) 
     staThread.SetApartmentState(ApartmentState.STA) 
     staThread.Start() 
     staThread.Join() 
     Return instance._ContainsText 
    End Function 
    Public Function ContainsText(ByVal format As Object) As Boolean 
     Dim instance As New ClipboardAsync 
     Dim staThread As New Thread(AddressOf instance._thContainsFileDropList) 
     staThread.SetApartmentState(ApartmentState.STA) 
     staThread.Start(format) 
     staThread.Join() 
     Return instance._ContainsText 
    End Function 

    Private _ContainsFileDropList As Boolean 
    Private Sub _thContainsFileDropList(ByVal format As Object) 
     Try 
      _ContainsFileDropList = Clipboard.ContainsFileDropList 
     Catch ex As Exception 
      _ContainsFileDropList = False 
     End Try 
    End Sub 
    Public Function ContainsFileDropList() As Boolean 
     Dim instance As New ClipboardAsync 
     Dim staThread As New Thread(AddressOf instance._thContainsFileDropList) 
     staThread.SetApartmentState(ApartmentState.STA) 
     staThread.Start() 
     staThread.Join() 
     Return instance._ContainsFileDropList 
    End Function 

    Private _GetFileDropList As Specialized.StringCollection 
    Private Sub _thGetFileDropList() 
     Try 
      _GetFileDropList = Clipboard.GetFileDropList 
     Catch ex As Exception 
      _GetFileDropList = Nothing 
     End Try 
    End Sub 
    Public Function GetFileDropList() As Specialized.StringCollection 
     Dim instance As New ClipboardAsync 
     Dim staThread As New Thread(AddressOf instance._thGetFileDropList) 
     staThread.SetApartmentState(ApartmentState.STA) 
     staThread.Start() 
     staThread.Join() 
     Return instance._GetFileDropList 
    End Function 
End Class 

Ecco la versione CSharp:

private class ClipboardAsync 
{ 

private string _GetText; 
private void _thGetText(object format) 
{ 
    try { 
     if (format == null) { 
      _GetText = Clipboard.GetText(); 
     } 
     else { 
      _GetText = Clipboard.GetText((TextDataFormat)format); 

     } 
    } 
    catch (Exception ex) { 
     //Throw ex 
     _GetText = string.Empty; 
    } 
} 
public string GetText() 
{ 
    ClipboardAsync instance = new ClipboardAsync(); 
    Thread staThread = new Thread(instance._thGetText); 
    staThread.SetApartmentState(ApartmentState.STA); 
    staThread.Start(); 
    staThread.Join(); 
    return instance._GetText; 
} 
public string GetText(TextDataFormat format) 
{ 
    ClipboardAsync instance = new ClipboardAsync(); 
    Thread staThread = new Thread(instance._thGetText); 
    staThread.SetApartmentState(ApartmentState.STA); 
    staThread.Start(format); 
    staThread.Join(); 
    return instance._GetText; 
} 

private bool _ContainsText; 
private void _thContainsText(object format) 
{ 
    try { 
     if (format == null) { 
      _ContainsText = Clipboard.ContainsText(); 
     } 
     else { 
      _ContainsText = Clipboard.ContainsText((TextDataFormat)format); 
     } 
    } 
    catch (Exception ex) { 
     //Throw ex 
     _ContainsText = false; 
    } 
} 
public bool ContainsText() 
{ 
    ClipboardAsync instance = new ClipboardAsync(); 
    Thread staThread = new Thread(instance._thContainsFileDropList); 
    staThread.SetApartmentState(ApartmentState.STA); 
    staThread.Start(); 
    staThread.Join(); 
    return instance._ContainsText; 
} 
public bool ContainsText(object format) 
{ 
    ClipboardAsync instance = new ClipboardAsync(); 
    Thread staThread = new Thread(instance._thContainsFileDropList); 
    staThread.SetApartmentState(ApartmentState.STA); 
    staThread.Start(format); 
    staThread.Join(); 
    return instance._ContainsText; 
} 

private bool _ContainsFileDropList; 
private void _thContainsFileDropList(object format) 
{ 
    try { 
     _ContainsFileDropList = Clipboard.ContainsFileDropList; 
    } 
    catch (Exception ex) { 
     //Throw ex 
     _ContainsFileDropList = false; 
    } 
} 
public bool ContainsFileDropList() 
{ 
    ClipboardAsync instance = new ClipboardAsync(); 
    Thread staThread = new Thread(instance._thContainsFileDropList); 
    staThread.SetApartmentState(ApartmentState.STA); 
    staThread.Start(); 
    staThread.Join(); 
    return instance._ContainsFileDropList; 
} 

private Specialized.StringCollection _GetFileDropList; 
private void _thGetFileDropList() 
{ 
    try { 
     _GetFileDropList = Clipboard.GetFileDropList; 
    } 
    catch (Exception ex) { 
     //Throw ex 
     _GetFileDropList = null; 
    } 
} 
public Specialized.StringCollection GetFileDropList() 
{ 
    ClipboardAsync instance = new ClipboardAsync(); 
    Thread staThread = new Thread(instance._thGetFileDropList); 
    staThread.SetApartmentState(ApartmentState.STA); 
    staThread.Start(); 
    staThread.Join(); 
    return instance._GetFileDropList; 
} 
} 

è possibile utilizzare semplici con: Vb.net:

Dim Clipboard2 As New ClipboardAsync 
MessageBox.Show (Clipboard2.ContainsText()) 

Csharp:

ClipboardAsync Clipboard2 = new ClipboardAsync(); 
MessageBox.Show (Clipboard2.ContainsText()); 
31

Onestamente, non so quello che un thread STA è, ma in progetti semplici che potrebbe risolvere il problema di aggiungere [STAThread] destra prima del metodo Main:

[STAThread] 
static void Main(string[] args) 
{ (...) 

funziona per me, così io non mettono in discussione il metodo;)


Ulteriori informazioni sul decoratore [STAThread] sono disponibili nel post di blog Why is STAThread required?.

+1

Oh Dio questo mi ha aiutato MOLTO !! Grazie mille! – theknut

+0

Perfetto per un'app rapida per console. – Grant

+1

Vorrei poter continuare a votare più e più volte. – Max

1

Questo è un problema di threading. Dobbiamo ottenere il filo giusto ed eseguire attraverso i delegati.

Sto aggiornando le mie proprietà tramite un timer che trascorre ogni 500 ms.Ecco il codice:

public delegate void ClipboarDelegate(); 

    ClipboarDelegate clipboardDelegate = null; 

    void clipboardTimer_Elapsed(object sender, ElapsedEventArgs e) 
    { 
     if (clipboardDelegate == null) 
      clipboardDelegate = ClipboarDelegateMethod; 

     //Here we get the right thread, most probably the application thread 
     Application.Current.Dispatcher.BeginInvoke(clipboardDelegate); 
    } 

    public void ClipboarDelegateMethod() 
    { 
     try 
     { 
      if (Clipboard.ContainsData(DataFormats.Text)) 
      { 
       //It's important to lock this section 
       lock (ClipboardString) 
       { 
        ClipboardString = Clipboard.GetData(DataFormats.Text) as string; 
       } 
      } 
     } 
     catch 
     { } 
    } 

Inoltre ho fatto un DependencyProperty adeguato con ClipboardString:

public static readonly DependencyProperty ClipboardStringDP = 
     DependencyProperty.Register("ClipboardString", 
            typeof(string), 
            typeof(MainWindow), 
            new UIPropertyMetadata(string.Empty)); 

    public string ClipboardString 
    { 
     get { return (string)this.GetValue(ClipboardStringDP); } 
     set { this.SetValue(ClipboardStringDP, value); } 
    } 

In questo modo può essere legato alla mia TextBox in XAML assumendo mio controllo o finestra x:Name="_this":

<TextBox Name="ClipBoardTextBox" 
     DataContext="{Binding ElementName=_this}" 
     Text="{Binding Path=ClipboardString, Mode=OneWay}"/> 
+0

Si tratta di un'altra risposta alla domanda originale? Se è così, allora cosa offre di nuovo? – ClickRick

5

Il codice BoltBait non ha funzionato per IDataObject perché l'oggetto dati perde le informazioni all'esterno del thread. Tutto funziona correttamente, se IDataObject viene utilizzato solo all'interno del thread in questo modo:

IDataObject idat = null; 
Exception threadEx = null; 
String text = ""; 
Thread staThread = new Thread(
    delegate() 
    { 
     try 
     { 
      idat = Clipboard.GetDataObject(); 
      text = idat.GetData(DataFormats.Text) 
     } 

     catch (Exception ex) 
     { 
      threadEx = ex;    
     } 
    }); 
staThread.SetApartmentState(ApartmentState.STA); 
staThread.Start(); 
staThread.Join(); 
// here you can use text, which contains data from clipboard 
Problemi correlati