2009-02-06 124 views
36

我的剪贴板填充了文本,但是当我运行Clipboard.GetText返回null(空字符串)

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

我找回一个空字符串。我玩过各种形式的电话,包括:

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

但是结果相同。

我错过了一些明显的东西吗?

+0

你怎么把数据放在剪贴板? – 2009-02-06 01:03:59

+0

剪贴板上的数据是“文本”,而不是图形,音频或其他数据? – JMD 2009-02-06 01:07:27

回答

45

您只能从STA线程访问剪贴板。 Rick Brewster在Paint.NET中对常规的Edit-> Paste命令进行了一些重构。

代码:

​​

代码为里克。 http://forums.getpaint.net/index.php?/topic/13712-/page__view__findpost__p__226140

更新Jason Heine取得delegate后加入()修复暧昧方法错误的好点。

+5

不确定其他框架,但在.net 4.0委托中需要有(),否则你会得到一个模糊的方法错误。 – CodeLikeBeaker 2011-08-09 17:08:41

+0

我们应该添加一些锁定吗? – Toto 2014-12-30 16:24:24

+0

好的答案,虽然在我的情况下,它只是我有一个WinForms,我已经删除了Main上的[STAThread]属性,所以我只好把它放回去。 – 2016-06-29 16:11:08

0

由于某种原因,BoltBait的代码没有起作用(甚至在staThread.Join()之后,idat仍然为空)。我只是在staThread委托里面做了Clipboard.GetText(),而不是Clipboard.GetDataObject(),并且工作正常。

谢谢您的好意 - 你的代码片段让我有99%的:)

9

我写了这个类,它的工作原理,并做同样的事情,正好可以很容易地改善添加你需要

谁的方法
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 

这里是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; 
} 
} 

你可以简单的使用它: Vb.net:

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

Csharp的:

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

老实说,我不知道一个STA线程是什么,但在简单的项目,它可能解决问题的方法Main前右加[STAThread]

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

它为我,所以我不怀疑的方法)


有关[STAThread]装饰者的更多信息在博客文章上Why is STAThread required?

1

这是一个线程问题。我们必须获得正确的线程并通过代表执行。

我正在更新我的属性,通过计时器每500毫秒流逝。下面是代码:

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 
     { } 
    } 

而且我做了一个正确的DependencyProperty与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); } 
    } 

这样,它可以绑定到我的XAML文本框假设我的控制或窗口x:Name="_this"

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

BoltBait的代码不适用于IDataObject,因为数据对象在线程外部丢失了信息。一切工作正常,如果IDataObject只用于这样的线程内:

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