2009-02-06 43 views
36

vào clipboard của tôi được phổ biến với văn bản, nhưng khi tôi chạyClipboard.GetText trả về null (chuỗi rỗng)

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

tôi nhận lại một chuỗi rỗng. Tôi đã đùa giỡn với nhiều hình thức gọi khác nhau bao gồm:

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

Nhưng với cùng một kết quả.

Tôi có thiếu thứ gì đó hiển nhiên không?

+0

Làm cách nào để đưa dữ liệu vào khay nhớ tạm? –

+0

Dữ liệu nằm trên "văn bản" của bảng tạm và không phải là đồ họa, âm thanh hay khác? – JMD

Trả lời

45

Bạn chỉ có thể truy cập vào khay nhớ tạm từ chuỗi STA. Rick Brewster đã thực hiện việc này với một số việc tái cấu trúc lệnh Edit-> Paste thông thường, trong Paint.NET.

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 

Mã là từ Rick. http://forums.getpaint.net/index.php?/topic/13712-/page__view__findpost__p__226140

Cập nhật: Jason Heine làm một điểm tốt của việc thêm () sau delegate để sửa chữa các lỗi phương pháp mơ hồ.

+5

không chắc chắn về các khung công tác khác, nhưng trong đại biểu .net 4.0 cần phải có() sau đó, nếu không bạn sẽ gặp lỗi phương thức mơ hồ. – CodeLikeBeaker

+0

Chúng ta có nên thêm một số khóa? – Toto

+0

Câu trả lời hay, mặc dù trong trường hợp của tôi, đó chỉ là tôi đã có một WinForms, nơi tôi đã loại bỏ thuộc tính [STAThread] trên Main, vì vậy tôi phải đưa nó trở lại. –

0

Vì một số lý do mã của BoltBait không hoạt động (idat vẫn là null ngay cả sau staThread.Join()). Tôi chỉ cần làm Clipboard.GetText() bên trong của delegate staThread thay vì Clipboard.GetDataObject() và làm việc tốt.

Cảm ơn mặc dù - đoạn mã của bạn đã cho tôi 99% có :)

+0

Tuyệt vời. Tôi rất vui vì bạn đã làm việc. – BoltBait

+0

Xin chào Jonathan - Tôi đã thấy chính xác điều tương tự và đã làm điều tương tự. – Matt

9

Tôi đã viết lớp này, nó hoạt động, và làm điều tương tự và có thể dễ dàng cải thiện chỉ thêm các phương pháp người bạn cần

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 

đây là phiên bản 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; 
} 
} 

Bạn có thể sử dụng đơn giản nó với: Vb.net:

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

CSharp:

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

Thành thực mà nói, tôi không biết những gì một sợi STA, nhưng trong các dự án đơn giản, nó có thể giải quyết vấn đề để thêm [STAThread] ngay trước khi Main phương pháp:

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

Nó hoạt động đối với tôi, vì vậy tôi không nghi ngờ phương pháp này;)


Thông tin thêm về trang trí [STAThread] có trên bài đăng blog Why is STAThread required?.

+1

Ôi Chúa này đã giúp tôi rất nhiều !! Cám ơn rất nhiều! – theknut

+0

Hoàn hảo cho ứng dụng bảng điều khiển nhanh. – Grant

+1

Tôi ước tôi có thể upvote hơn và hơn nữa. – Max

1

Đây là vấn đề về luồng. Chúng ta phải lấy đúng chủ đề và thực hiện thông qua các đại biểu.

Tôi đang cập nhật thuộc tính của mình thông qua bộ hẹn giờ, cứ sau mỗi 500 ms sẽ mất hết.Đây là mã:

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

Hơn nữa tôi đã thực hiện một DependencyProperty thích hợp với 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); } 
    } 

Bằng cách này nó có thể được liên kết với TextBox của tôi trong XAML giả kiểm soát hoặc cửa sổ x:Name="_this" tôi:

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

Đây có phải là câu trả lời khác cho câu hỏi gốc không? Nếu vậy, thì nó cung cấp cái gì mới? – ClickRick

5

Mã của BoltBait không hoạt động đối với IDataObject vì đối tượng dữ liệu mất thông tin bên ngoài chuỗi. Mọi thứ hoạt động tốt, nếu IDataObject chỉ được sử dụng bên trong chuỗi như sau:

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 
Các vấn đề liên quan