C# Clipboard.GetText 返回 null(空字符串)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/518701/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Clipboard.GetText returns null (empty string)
提问by Matthew
My clipboard is populated with text, but when I run
我的剪贴板填充了文本,但是当我运行时
string clipboardData = Clipboard.GetText(System.Windows.Forms.TextDataFormat.Text);
I get back an empty string. I've toyed with various forms of the call including:
我得到一个空字符串。我玩过各种形式的电话,包括:
string clipboardData = Clipboard.GetText();
string clipboardData = Clipboard.GetText(System.Windows.Forms.TextDataFormat.UnicodeText);
But with the same result.
但结果相同。
Am I missing something obvious?
我错过了一些明显的东西吗?
采纳答案by BoltBait
You can only access the clipboard from an STA thread. Rick Brewster ran into this with some refactoring of the regular Edit->Paste command, in Paint.NET.
您只能从 STA 线程访问剪贴板。Rick Brewster 在 Paint.NET 中对常规 Edit->Paste 命令进行了一些重构,从而遇到了这个问题。
Code:
代码:
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
Code is from Rick. http://forums.getpaint.net/index.php?/topic/13712-/page__view__findpost__p__226140
代码来自 Rick。http://forums.getpaint.net/index.php?/topic/13712-/page__view__findpost__p__226140
Update: Jason Heinemade a good point of adding ()
after delegate
to fix the ambiguous method error.
更新:Jason Heine很好地添加了()
afterdelegate
以修复不明确的方法错误。
回答by Jonathan Yee
For some reason BoltBait's code didn't quite work (idat was still null even after staThread.Join()). I just did Clipboard.GetText() inside of the staThread delegate instead of Clipboard.GetDataObject() and that worked fine.
出于某种原因,BoltBait 的代码不能正常工作(即使在 staThread.Join() 之后,idat 仍然为空)。我只是在 staThread 委托中执行 Clipboard.GetText() 而不是 Clipboard.GetDataObject() 并且效果很好。
Thanks though - your code snippet got me 99% there :)
谢谢 - 你的代码片段让我 99% 有 :)
回答by Braian Bressan
I have written this class, it works, and do the same thing and can be easily improved just adding the method who you need
我已经编写了这个类,它可以工作,并且可以做同样的事情,只需添加您需要的方法即可轻松改进
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
Here is the CSharp Version:
这是 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;
}
}
You can simple use it with: Vb.net:
您可以简单地使用它:Vb.net:
Dim Clipboard2 As New ClipboardAsync
MessageBox.Show (Clipboard2.ContainsText())
Csharp:
夏普:
ClipboardAsync Clipboard2 = new ClipboardAsync();
MessageBox.Show (Clipboard2.ContainsText());
回答by Danilo Bargen
Honestly, I don't know what a STA thread is, but in simple projects it might solve the problem to add [STAThread]
right before the Main
method:
老实说,我不知道什么是 STA 线程,但是在简单的项目中,[STAThread]
在Main
方法之前添加它可能会解决问题:
[STAThread]
static void Main(string[] args)
{ (...)
It works for me, so I don't question the method ;)
它对我有用,所以我不质疑该方法;)
Further information about the [STAThread]
decorator is on blog post Why is STAThread required?.
关于[STAThread]
装饰器的更多信息在博客文章为什么需要 STAThread?.
回答by Rubarb
This is a threading problem. We have to get the right thread and execute through delegates.
这是一个线程问题。我们必须获得正确的线程并通过委托执行。
I am updating my properties through a timer elapsing every 500 ms. Here is the code:
我正在通过每 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
{ }
}
Moreover I've made a proper DependencyProperty with ClipboardString:
此外,我已经使用 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); }
}
This way it can be bound to my TextBox in XAML assuming my control or window x:Name="_this"
:
这样它就可以绑定到 XAML 中的我的 TextBox 假设我的控件或窗口x:Name="_this"
:
<TextBox Name="ClipBoardTextBox"
DataContext="{Binding ElementName=_this}"
Text="{Binding Path=ClipboardString, Mode=OneWay}"/>
回答by Tiina
BoltBait's code did not work for IDataObject because data object loses information outside the thread. Everything works fine, if the IDataObject is used only inside the thread like this:
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