簡體   English   中英

Clipboard.GetText 返回 null(空字符串)

[英]Clipboard.GetText returns null (empty string)

我的剪貼板中填充了文本,但是當我運行時

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

我得到一個空字符串。 我玩過各種形式的電話,包括:

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

但結果相同。

我錯過了一些明顯的東西嗎?

您只能從 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后添加()以修復模棱兩可的方法錯誤。

老實說,我不知道什么是 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())

夏普:

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); }
    }

這樣,假設我的控件或窗口x:Name="_this" ,它可以綁定到 XAML 中的 TextBox :

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

由於某種原因,BoltBait 的代碼不能很好地工作(即使在 staThread.Join() 之后,idat 仍然為空)。 我只是在 staThread 委托中做了 Clipboard.GetText() 而不是 Clipboard.GetDataObject() 並且效果很好。

不過謝謝 - 你的代碼片段讓我在那里 99% :)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM