2010-04-05 16 views
13

Ich werde mein Bestes tun, um im Detail zu erklären, was ich zu erreichen versuche.Wie kann ich die Systemzwischenablage in C# sichern und wiederherstellen?

Ich verwende C# mit IntPtr-Fenster-Handles, um eine CTRL-C-Kopieroperation für eine externe Anwendung aus meiner eigenen C# -Anwendung durchzuführen. Ich musste dies tun, weil es keine Möglichkeit gab, mit GET_TEXT direkt auf den Text zuzugreifen. Ich verwende dann den Textinhalt dieser Kopie in meiner Anwendung. Das Problem hier ist, dass ich jetzt die Zwischenablage überschrieben habe.

Was ich möchte in der Lage sein zu tun ist:

  1. Sicherung der ursprüngliche Inhalt der Zwischenablage, die von jeder Anwendung anders als meine eigene gesetzt worden sein könnte.
  2. Dann führen Sie die Kopie und speichern Sie den Wert in meiner Anwendung.
  3. Anschließend den ursprünglichen Inhalt der Zwischenablage wiederherstellen, damit der Benutzer weiterhin Zugriff auf seine ursprünglichen Daten in der Zwischenablage hat.

Dies ist der Code, den ich bisher versucht habe:

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

ich die System.Windows.Clipboard verwenden und nicht die System.Windows.Forms.Clipboard. Der Grund dafür war, dass, als ich die STRG-C ausführte, die Clipboard-Klasse von System.Windows.Forms keine Daten zurückgab, sondern die Systemzwischenablage.

Ich schaute in einige der Low-Level-Benutzer32 Anrufe wie OpenClipboard, EmptyClipboard und CloseClipboard in der Hoffnung, dass sie mir helfen würde dies zu tun, aber bisher bekomme ich COM-Ausnahmen beim Versuch, wiederherzustellen.

Ich dachte, dass dies vielleicht mit dem OpenClipboard-Parameter zu tun hat, der ein IntPtr-Fensterhandle der Anwendung erwartet, die die Kontrolle über die Zwischenablage übernehmen will. Da ich erwähnt habe, dass meine Anwendung keine GUI hat, ist das eine Herausforderung. Ich war mir nicht sicher, was ich hier passieren sollte. Vielleicht kann jemand etwas Licht dazu bringen?

Benutzt ich die Zwischenablage-Klasse falsch? Gibt es eine klare Möglichkeit, das IntPtr-Fensterhandle einer Anwendung ohne GUI zu erhalten? Kennt jemand eine bessere Möglichkeit zum Sichern und Wiederherstellen der System-Zwischenablage?

+0

Ich lief in den gleichen Fehler und fand diesen Beitrag. Dieser Fehler tritt jedoch nur auf, wenn ich Clipboard.GetDataObject(). SetData (myData) aufruft. Es funktioniert gut, wenn ich Clipboard.SetDataObject (myData) aufrufe. Irgendeine Erklärung warum? Meine App basiert auf WPF, wenn es darauf ankommt. – newman

Antwort

6

Sie können den Inhalt der Zwischenablage in einem Wörterbuch speichern und wiederherstellen danach:

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

Das Problem, das ich habe, ist, dass jedes SetData oder SetDataObject, das ich ausführe, mir eine COM-Ausnahme gibt, weil es die Zwischenablage nicht öffnen konnte. Ich werde diese Methode versuchen, aber das zugrunde liegende Problem ist die Zwischenablage scheint gesperrt. – gtaborga

+1

Dies ist die Ausnahme, die ich beim ersten SetData-Aufruf in dieser Schleife bekomme: "SetData auf einem eingefrorenen OLE-Datenobjekt nicht setzen" – gtaborga

+0

Probiere Clipboard.SetData anstelle von IDataObject.SetData, dann ... –

17

Es ist Torheit, um zu versuchen, dies zu tun. Sie können die Zwischenablage nicht originalgetreu wiederherstellen. Es kann Dutzende von nicht gerenderten Datenformaten geben, die das verzögerte Rendern verwenden. Wenn Sie versuchen, sie alle zu rendern, werden die Ressourcen in der Quellanwendung nicht mehr ausreichen. Es ist wie in ein Restaurant zu gehen und zu sagen: "Gib mir eins von allem".

Angenommen, der Benutzer hat 500 Zeilen x 100 Spalten in Excel ausgewählt und in die Zwischenablage kopiert. Excel "wirbt", dass es diese Daten in etwa 25 verschiedenen Formaten einschließlich Bitmap produzieren kann. Sobald Sie es als Bitmap einfügen, zwingen Sie Excel, es als Bitmap darzustellen. Das sind 50000 Zellen und wäre eine Bitmap ca. 10.000 x 15.000 Pixel. Und Sie erwarten, dass der Benutzer wartet, während Excel das hustet, zusammen mit 24 anderen Formaten? Nicht durchführbar.

Darüber hinaus werden Sie WM_DrawClipboard-Ereignisse auslösen, die sich auf andere Betrachter in der Zwischenablage auswirken.

Geben Sie auf.

+5

"Programme sollten Daten nicht ohne ausdrückliche Anweisung des Benutzers in unsere Zwischenablage übertragen." - Charles Petzold, Programmierung von Windows 3.1, Microsoft Press, 1992 –

+0

Das wäre der Grund, warum ich jemals die Zwischenablage bearbeitet habe Code war beim Implementieren Ausschneiden, Kopieren und Einfügen in einem Menü in einer .NET-Anwendung. – Powerlord

+0

Ich wollte nie alle Daten sichern, die gesichert werden. Die Menge der mit CTRL-C abgerufenen Daten entspricht der Länge eines Satzes im Text. Ich hatte gehofft, dass ich den ursprünglichen Inhalt der Zwischenablage wiederherstellen kann, nachdem ich die Zwischenablage für meine eigenen Bedürfnisse benutzt habe. Ist es sogar möglich, die Zwischenablage wiederherzustellen, ohne dass in diesem Szenario der Fehler "Zwischenablage nicht öffnen" angezeigt wird? – gtaborga