2010-04-05 50 views
13

Tôi sẽ cố hết sức để giải thích chi tiết những gì tôi đang cố gắng đạt được.Làm cách nào để sao lưu và khôi phục khay nhớ tạm của hệ thống trong C#?

Tôi đang sử dụng C# với trình điều khiển cửa sổ IntPtr để thực hiện thao tác sao chép CTRL-C trên ứng dụng bên ngoài từ ứng dụng C# của riêng tôi. Tôi phải làm điều này vì không có cách nào để truy cập trực tiếp văn bản bằng cách sử dụng GET_TEXT. Sau đó tôi sử dụng nội dung văn bản của bản sao đó trong ứng dụng của tôi. Vấn đề ở đây là bây giờ tôi đã ghi đè lên clipboard.

Những gì tôi muốn để có thể làm là:

  1. Sao lưu các nội dung ban đầu của clipboard mà có thể đã được thiết lập bởi bất kỳ ứng dụng khác hơn là của riêng tôi.
  2. Sau đó, thực hiện sao chép và lưu trữ giá trị vào ứng dụng của tôi.
  3. Sau đó, khôi phục nội dung gốc của khay nhớ tạm để người dùng vẫn có quyền truy cập vào dữ liệu khay nhớ tạm gốc của mình.

Đây là mã tôi đã cố gắng cho đến nay:

private void GetClipboardText() 
{ 

    text = ""; 

    IDataObject backupClipboad = Clipboard.GetDataObject(); 

    KeyboardInput input = new KeyboardInput(this); 
    input.Copy(dialogHandle); // Performs a CTRL-C (copy) operation 

    IDataObject clipboard = Clipboard.GetDataObject(); 
    if (clipboard.GetDataPresent(DataFormats.Text)) 
    { 
     // Retrieves the text from the clipboard 
     text = clipboard.GetData(DataFormats.Text) as string; 
    } 

    if (backupClipboad != null) 
    { 
     Clipboard.SetDataObject(backupClipboad, true); // throws exception 
    } 
} 

Tôi đang sử dụng System.Windows.Clipboard và không phải là System.Windows.Forms.Clipboard. Lý do cho điều này là khi tôi thực hiện CTRL-C, lớp Clipboard từ System.Windows.Forms không trả về bất kỳ dữ liệu nào, nhưng clipboard của hệ thống đã làm.

Tôi đã xem xét một số cuộc gọi user32 mức thấp như OpenClipboard, EmptyClipboard và CloseClipboard với hy vọng rằng chúng sẽ giúp tôi thực hiện điều này nhưng cho đến nay tôi vẫn gặp ngoại lệ COM khi cố khôi phục.

Tôi nghĩ có lẽ điều này phải làm với tham số OpenClipboard đang mong đợi một cửa sổ xử lý IntPtr của ứng dụng muốn kiểm soát clipboard. Vì tôi đã đề cập rằng ứng dụng của tôi không có GUI nên đây là một thách thức. Tôi đã không chắc chắn những gì để vượt qua ở đây. Có lẽ ai đó có thể làm sáng tỏ điều đó?

Tôi có sử dụng lớp Clipboard không chính xác không? Có một cách rõ ràng để có được xử lý cửa sổ IntPtr của một ứng dụng không có GUI? Có ai biết một cách tốt hơn để sao lưu và khôi phục lại clipboard hệ thống?

+0

Tôi đã gặp lỗi tương tự và tìm thấy bài đăng này. Tuy nhiên, tôi nhận được lỗi này chỉ khi tôi gọi Clipboard.GetDataObject(). SetData (myData). Nó hoạt động tốt nếu tôi gọi Clipboard.SetDataObject (myData). Bất kỳ lời giải thích tại sao? Ứng dụng của tôi dựa trên WPF nếu nó quan trọng. – newman

Trả lời

6

Bạn có thể lưu các nội dung của clipboard trong một cuốn từ điển, và khôi phục lại nó sau đó:

public IDictionary<string, object> GetClipboardData() 
{ 
    var dict = new Dictionary<string, object>(); 
    var dataObject = Clipboard.GetDataObject(); 
    foreach(var format in dataObject.GetFormats()) 
    { 
     dict.Add(format, dataObject.GetData(format)); 
    } 
    return dict; 
} 

public void SetClipboardData(IDictionary<string, object> dict) 
{ 
    var dataObject = Clipboard.GetDataObject(); 
    foreach(var kvp in dict) 
    { 
     dataObject.SetData(kvp.Key, kvp.Value); 
    } 
} 

... 

var backup = GetClipboardData(); 
// Do something with the clipboard... 
... 
SetClipboardData(backup); 
+0

Vấn đề tôi gặp phải là bất kỳ SetData hoặc SetDataObject tôi thực hiện cho tôi một ngoại lệ COM vì nó không thể mở clipboard. Tôi sẽ thử phương pháp đó nhưng vấn đề cơ bản là clipboard dường như bị khóa. – gtaborga

+1

Đây là ngoại lệ tôi nhận được về các cuộc gọi SetData đầu tiên trong vòng lặp rằng: "Không thể SetData trên một đối tượng dữ liệu OLE đông lạnh" – gtaborga

+0

Hãy thử Clipboard.SetData thay vì IDataObject.SetData, sau đó ... –

17

Đó là sự điên rồ để cố gắng thực hiện điều này. Bạn không thể khôi phục lại clipboard một cách trung thực về trạng thái trước đó của nó. Có thể có hàng tá định dạng dữ liệu chưa được xuất hiện có sử dụng "hiển thị bị trễ" và nếu bạn cố gắng hiển thị tất cả, bạn sẽ khiến ứng dụng nguồn cạn nguồn tài nguyên. Nó giống như bước vào một nhà hàng và nói "hãy cho tôi một trong mọi thứ".

Giả sử người dùng đã chọn 500 hàng x 100 cột trong Excel và đã sao chép vào bảng tạm. Excel "quảng cáo" rằng nó có thể tạo ra dữ liệu này trong khoảng 25 định dạng khác nhau, bao gồm cả Bitmap. Một khi bạn dán nó như là một Bitmap, bạn buộc Excel để render nó như là một bitmap. Đó là 50000 ô, và sẽ là một bitmap khoảng 10.000 x 15.000 pixel. Và bạn mong đợi người dùng chờ đợi trong khi Excel ho lên, cùng với 24 định dạng khác? Không khả thi.

Hơn nữa, bạn sẽ kích hoạt sự kiện WM_DrawClipboard, điều này sẽ ảnh hưởng đến người xem khay nhớ tạm khác.

Bỏ cuộc.

+5

“Chương trình không nên chuyển dữ liệu vào ra của chúng ta về clipboard mà không có một hướng dẫn rõ ràng từ người sử dụng.” - Charles Petzold, Lập trình Windows 3.1, Microsoft Press, 1992 –

+0

Đó sẽ là lý do tại sao lần duy nhất mà tôi từng viết xử lý Clipboard là khi triển khai Cắt, Sao chép và Dán trong một menu trong ứng dụng .NET. – Powerlord

+0

Tôi không bao giờ có ý định hiển thị tất cả dữ liệu đang được sao lưu. Lượng dữ liệu được truy xuất bằng CTRL-C là khoảng thời gian của một câu trong văn bản. Tôi đã hy vọng cho một cách để đưa trở lại nội dung ban đầu của clipboard sau khi sử dụng clipboard cho nhu cầu của riêng tôi. Nó thậm chí có thể khôi phục lại clipboard mà không nhận được một lỗi 'không thể mở clipboard' trong kịch bản này? – gtaborga

Các vấn đề liên quan