我的剪贴板中填充了文字,但是当我运行
时string clipboardData = Clipboard.GetText(System.Windows.Forms.TextDataFormat.Text);
我找回一个空字符串。我玩弄了各种形式的电话,包括:
string clipboardData = Clipboard.GetText();
string clipboardData = Clipboard.GetText(System.Windows.Forms.TextDataFormat.UnicodeText);
但结果相同。
我错过了一些明显的东西吗?
答案 0 :(得分:51)
您只能从STA线程访问剪贴板。 Rick Brewster在Paint.NET中对常规的Edit-> Paste命令进行了一些重构。
代码:
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
来解决模糊方法错误。
答案 1 :(得分:35)
老实说,我不知道STA线程是什么,但在简单的项目中,它可以解决在[STAThread]
方法之前添加Main
的问题:
[STAThread]
static void Main(string[] args)
{ (...)
它对我有用,所以我不会质疑这个方法;)
有关[STAThread]
装饰器的更多信息,请参阅博客文章 Why is STAThread required? 。
答案 2 :(得分: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());
答案 3 :(得分:6)
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
答案 4 :(得分: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
{ }
}
此外,我使用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中的TextBox,假设我的控件或窗口x:Name="_this"
:
<TextBox Name="ClipBoardTextBox"
DataContext="{Binding ElementName=_this}"
Text="{Binding Path=ClipboardString, Mode=OneWay}"/>
答案 5 :(得分:0)
出于某种原因,BoltBait的代码不能正常工作(即使在staThread.Join()之后,idat仍为null)。我刚刚在staThread委托中使用Clipboard.GetText()而不是Clipboard.GetDataObject(),并且工作正常。
非常感谢 - 你的代码片段让我99%:)