2016-10-03 199 views
1

我維護一個WPF .NET應用程序,並且用戶在試圖從DataGrid控件中複製時遇到了崩潰。我搜索了一下,發現原因是他使用的其他應用程序可能不會撥打CloseClipboard()。在相同的情況下,Excel也給出了一條錯誤消息,消息「我們無法釋放剪貼板上的空間。另一個程序現在可能正在使用它。'使用Windows剪貼板

然後我寫了,有一個按鈕,打開/關閉剪貼板另一個程序,然後我可以重現此問題,我實現了相同的「修復」,只需一個錯誤消息。

但是,出於好奇,我想看看Google Chrome如何處理這個問題。我使用我的程序鎖定了剪貼板,並確認Excel正在抱怨。但Chrome仍然能夠正確處理複製/粘貼。我可以從Chrome複製到記事本中,但不能從記事本和Excel中複製。有趣的是,我實際上可以從記事本複製到Chrome。

我一直在瀏覽Chromium的源代碼,但是我找不到複製/粘貼邏輯的實現。有誰知道Chrome如何處理這個?

而且這怎麼可能,我不能記事本中複製/粘貼,而是從記事本到Chrome瀏覽器工作正常?

在所有的實現,我可以在網上找到的解決方案似乎是一樣的我現在:要嘗試幾次在一秒鐘左右,才放棄。

以供參考,這是後面的代碼爲我的剪貼板更衣室:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 

namespace ClipboardLocker 
{ 
    public partial class MainWindow : Window 
    { 
     [System.Runtime.InteropServices.DllImport("user32.dll")] 
     static extern IntPtr GetOpenClipboardWindow(); 

     [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)] 
     static extern bool OpenClipboard(IntPtr hWndNewOwner); 

     [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)] 
     static extern bool CloseClipboard(); 

     bool clipboardLocked = false; 

     public MainWindow() 
     { 
      InitializeComponent(); 

      double screenWidth = System.Windows.SystemParameters.PrimaryScreenWidth; 
      double screenHeight = System.Windows.SystemParameters.PrimaryScreenHeight; 
      double windowWidth = this.Width; 
      double windowHeight = this.Height; 
      this.Left = (screenWidth/2) - (windowWidth/2); 
      this.Top = (screenHeight/2) - (windowHeight/2); 
     } 

     private void LockButton_Click(object sender, RoutedEventArgs e) 
     { 
      if (!clipboardLocked) 
      { 
       IntPtr handle = GetOpenClipboardWindow(); 
       OpenClipboard(handle); 
       clipboardLocked = true; 
       LockButton.Content = "Unlock"; 
      } 
      else 
      { 
       CloseClipboard(); 
       clipboardLocked = false; 
       LockButton.Content = "Lock"; 
      } 
     } 
    } 
} 

[更新]

經過一些實驗,似乎Chrome是能夠以某種方式解鎖剪貼板。在Chrome中完成複製/粘貼後,它也可以在其他應用程序中使用。 Chromw如何從我的儲物櫃程序中「偷」剪貼板? MSDN mentioins ChangeClipboardChain。我會試着去嘗試一下。

+0

你有沒有使用的WinForms剪貼板類測試(https://msdn.microsoft.com/en-us/library/system.windows.forms.clipboard(v=vs.110).aspx)並看看他們的行爲是否有所不同?不知道是否會,只是一個想法。 – Yushatak

+0

@Yushatak是的,WinForms剪貼板方法使用'嘗試幾次'循環,而WPF剪貼板方法不使用,只是立即拋出異常。據我所知,沒有其他區別。 – Istarnion

+0

看起來像CloseClipboard不需要任何參數,因此可能在處理該異常的地方嘗試調用CloseClipboard並重試? – Yushatak

回答

1

接管剪貼板,我先請OpenClipboardNULL說法。這會從當前擁有它的任何窗口中「竊取」剪貼板。然後我打電話給CloseClipboard關閉它。現在這將工作,因爲剪貼板將是'開放的剪貼板與當前任務相關聯',正如MSDN所說的那樣。

現在剪貼板正確關閉,或者叫WPF的或Windows窗體Clipboard.SetText()作品。

這當然不是一個很好的解決方案,但我相信這是Windows給我們的最佳選擇。

這裏是我的ClipboardHelper,如果其他人面臨這個問題。

static class ClipboardHelper 
{ 
    [System.Runtime.InteropServices.DllImport("user32.dll")] 
    static extern IntPtr GetOpenClipboardWindow(); 

    [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)] 
    static extern bool OpenClipboard(IntPtr hWndNewOwner); 

    [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)] 
    static extern bool CloseClipboard(); 

    [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)] 
    static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext); 

    public static bool SetText(string text) 
    { 
     IntPtr hWnd = GetOpenClipboardWindow(); // Gets the HWND of the window that currently owns the clipboard 

     if (hWnd == null) // If no window currently owns the clipboard, just go ahead and set the text. 
     { 
      System.Windows.Forms.Clipboard.SetText(text); 
     } 
     else 
     { 
      OpenClipboard(IntPtr.Zero); 
      CloseClipboard(); 
      System.Windows.Forms.Clipboard.SetText(text); 
     } 
     return true; 
    } 
} 
0

將數據寫入JSON文件而不是剪貼板。由於這個原因,即使程序將被關閉,您也可以訪問值。

+0

我認爲他沒有將它用作數據存儲,而是需要特別的剪貼板支持? – Yushatak

+0

是的,用例是在我的應用程序和excel之間複製/粘貼。 – Istarnion