Clipboard.GetText返回null(空string)
我的剪贴板填充文本,但是当我运行
string clipboardData = Clipboard.GetText(System.Windows.Forms.TextDataFormat.Text);
我找回一个空的string。 我玩过各种forms的电话,包括:
string clipboardData = Clipboard.GetText(); string clipboardData = Clipboard.GetText(System.Windows.Forms.TextDataFormat.UnicodeText);
但是结果一样。
我错过了什么明显的?
您只能从STA线程访问剪贴板。 里克·布鲁斯特(Rick Brewster)在Paint.NET中对常规编辑 – >粘贴命令进行了一些重构。
码:
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
代码来自Rick。 http://forums.getpaint.net/index.php?/topic/13712-/page__view__findpost__p__226140
更新 : Jason Heine在delegate
之后添加了()
以修复模糊的方法错误。
老实说,我不知道STA线程是什么,但是在简单的项目中,它可以解决在Main
方法之前添加[STAThread]
的问题:
[STAThread] static void Main(string[] args) { (...)
它适用于我,所以我不质疑的方法;)
有关[STAThread]
装饰器的更多信息在博客文章中为什么要求STAThread? 。
我已经写了这个类,它工作,并做同样的事情,可以很容易地改善,只是添加你需要的方法
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());
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
这是一个线程问题。 我们必须得到正确的线程,并通过代表执行。
我正在更新我的属性通过一个计时器每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 { } }
此外,我用ClipboardString做了一个适当的DependencyProperty:
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}"/>
由于某种原因,BoltBait的代码不起作用(甚至在staThread.Join()之后,idat仍然是空的)。 我只是在staThread委托而不是Clipboard.GetDataObject()的内部做了Clipboard.GetText(),而且工作正常。
谢谢 – 你的代码片段让我有99%的:)