2017-11-17 14 views
1

私はクリップボードから以下のコードでデータを取得しようとしています。メイン以外のスレッドでクリップボードデータを取得する方法は?

var textFromMain = Clipboard.GetText(TextDataFormat.Text);

をしかし、下の行は、空の文字列または空白の文字列を返す -

private void TestBtn_Click(object sender, EventArgs e) 
{ 
Thread sampleThread = new Thread(SampleMethod); 
sampleThread.IsBackground = true; 
sampleThread.Start(); 
Thread.Sleep(2000); 
var textFromMain = Clipboard.GetText(TextDataFormat.Text); 
} 

private void SampleMethod() 
{ 
var textFromThread = Clipboard.GetText(TextDataFormat.Text); 
Thread.Sleep(1000); 
} 

私はこの行をクリップボードにコピーしたものは何でもテキスト取得しています。

var textFromThread = Clipboard.GetText(TextDataFormat.Text);

私は問題だ何届きません。誰かが私に理解を助けることができますか?マルチスレッドの場合は、正しい方向に向けるようにしてください。

答えて

1

最後に、以下の方法でクリップボードテキストにアクセスしました。

private string GetClipBoradData() 
    { 
     try 
     { 
      string clipboardData= null; 
      Exception threadEx = null; 
      Thread staThread = new Thread(
       delegate() 
       { 
        try 
        { 
         clipboardData= Clipboard.GetText(TextDataFormat.Text); 
        } 

        catch (Exception ex) 
        { 
         threadEx = ex; 
        } 
       }); 
      staThread.SetApartmentState(ApartmentState.STA); 
      staThread.Start(); 
      staThread.Join(); 
      return clipboardData; 
     } 
     catch (Exception exception) 
     { 
      return string.Empty; 
     } 
    } 
2

Clipboard.GetText(TextDataFormat.Text)はCOMを使用し、STAThreadAttributeでマークされていないスレッドで呼び出された場合は例外をスローします。

解決方法の1つは、Invokeを使用してClipboard.GetTextの呼び出しをメインスレッドに戻すための使用代理人です。しかし、この場合、スレッドは、SampleMethod()がメインフォームスレッドで実行を終了し、メインスレッドが解放されるまでInvokeで実行をフリーズします。

他の方法は、System.Windows.Forms.Clipboard.GetText()の代わりにクリップボードのテキストを取得するためにCOMへの独自の呼び出しを使用することです。ClipboardCom.GetText()を参照してください。

private string _textFromMain, _textFromThreadByInvoke, _textFromThreadByCom; 

    private delegate string GetClipboardInvoke(TextDataFormat textformat); 
    private void SampleInvokeMethod() 
    { 
     GetClipboardInvoke invokerClipboard = new GetClipboardInvoke(Clipboard.GetText); 
     _textFromThreadByInvoke = (string)this.Invoke(invokerClipboard, TextDataFormat.Text); // where this is a Form 
     Thread.Sleep(1000); 
    } 



    private void button1_Click(object sender, EventArgs e) 
    { 
     Thread sampleInvokeThread = new Thread(SampleInvokeMethod) { IsBackground = true }; 
     sampleInvokeThread.Start(); 

     Thread sampleComThread = new Thread(SampleComMethod) { IsBackground = true }; 
     sampleComThread.Start(); 

     Thread.Sleep(10000); 
     _textFromMain = Clipboard.GetText(TextDataFormat.Text); 
    } 


    private void SampleComMethod() 
    { 
     _textFromThreadByCom = ClipboardCom.GetText(); 
     Thread.Sleep(1000); 
    } 

    public static class ClipboardCom 
    { 
     [DllImport("user32.dll")] 
     static extern IntPtr GetClipboardData(uint uFormat); 
     [DllImport("user32.dll")] 
     static extern bool IsClipboardFormatAvailable(uint format); 
     [DllImport("user32.dll", SetLastError = true)] 
     static extern bool OpenClipboard(IntPtr hWndNewOwner); 
     [DllImport("user32.dll", SetLastError = true)] 
     static extern bool CloseClipboard(); 
     [DllImport("kernel32.dll")] 
     static extern IntPtr GlobalLock(IntPtr hMem); 
     [DllImport("kernel32.dll")] 
     static extern bool GlobalUnlock(IntPtr hMem); 

     const uint CF_UNICODETEXT = 13; 

     public static string GetText() 
     { 
      if (!IsClipboardFormatAvailable(CF_UNICODETEXT)) 
       return null; 
      if (!OpenClipboard(IntPtr.Zero)) 
       return null; 

      string data = null; 
      var hGlobal = GetClipboardData(CF_UNICODETEXT); 
      if (hGlobal != IntPtr.Zero) 
      { 
       var lpwcstr = GlobalLock(hGlobal); 
       if (lpwcstr != IntPtr.Zero) 
       { 
        data = Marshal.PtrToStringUni(lpwcstr); 
        GlobalUnlock(lpwcstr); 
       } 
      } 
      CloseClipboard(); 

      return data; 
     } 
    } 
+0

助けてくれてありがとうございますが、別の短い方法で終了しました。それを答えに加える。 –

関連する問題