2010-04-05 2 views
13

Je ferai de mon mieux pour expliquer en détail ce que j'essaie d'accomplir.Comment sauvegarder et restaurer le presse-papiers du système en C#?

J'utilise C# avec des poignées de fenêtre IntPtr pour effectuer une opération de copie CTRL-C sur une application externe à partir de ma propre application C#. Je devais le faire parce qu'il n'y avait aucun moyen d'accéder directement au texte en utilisant GET_TEXT. J'utilise alors le contenu textuel de cette copie dans mon application. Le problème ici est que j'ai maintenant écrasé le presse-papiers.

Ce que je voudrais être en mesure de faire est:

  1. sauvegarde le contenu du presse-papiers d'origine qui aurait pu être fixé par une application autre que moi-même.
  2. Puis effectuez la copie et stockez la valeur dans mon application.
  3. Ensuite, restaurez le contenu d'origine du presse-papiers afin que l'utilisateur ait toujours accès à ses données de presse-papiers d'origine.

C'est le code que je l'ai essayé jusqu'à présent:

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

J'utilise le System.Windows.Clipboard et non la System.Windows.Forms.Clipboard. La raison de ceci était que quand j'ai exécuté le CTRL-C, la classe de Presse-papiers de System.Windows.Forms n'a renvoyé aucune donnée, mais le presse-papiers du système l'a fait. J'ai examiné quelques-uns des appels de bas niveau user32 comme OpenClipboard, EmptyClipboard et CloseClipboard en espérant qu'ils aideraient à faire cela, mais jusqu'à présent je continue à obtenir des exceptions COM en essayant de restaurer.

Je pensais que peut-être cela avait à voir avec le paramètre OpenClipboard qui attend un handle de fenêtre IntPtr de l'application qui veut prendre le contrôle du presse-papiers. Depuis que j'ai mentionné que mon application n'a pas de GUI c'est un défi. Je n'étais pas sûr de ce qu'il fallait passer ici. Peut-être que quelqu'un peut faire la lumière sur cela? Est-ce que j'utilise incorrectement la classe Presse-papiers? Existe-t-il un moyen clair d'obtenir le handle de fenêtre IntPtr d'une application sans interface graphique? Est-ce que quelqu'un sait d'une meilleure façon de sauvegarder et de restaurer le presse-papiers du système?

+0

J'ai rencontré la même erreur et trouvé ce post. Cependant, j'ai cette erreur seulement si j'appelle Clipboard.GetDataObject(). SetData (myData). Cela fonctionne très bien si j'appelle Clipboard.SetDataObject (myData). Toute explication pourquoi? Mon application est basée sur WPF si c'est important. – newman

Répondre

6

Vous pouvez enregistrer le contenu du presse-papier dans un dictionnaire, et restaurer ensuite:

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

Le problème que j'ai est que n'importe quel SetData ou SetDataObject que j'effectue me donne une exception COM parce qu'il n'a pas réussi à ouvrir le presse-papiers. Je vais essayer cette méthode mais le problème sous-jacent est que le presse-papiers semble bloqué. – gtaborga

+1

Ceci est l'exception que je reçois sur le premier appel SetData dans cette boucle: "Can not SetData sur un objet de données OLE gelé" – gtaborga

+0

Essayez Clipboard.SetData au lieu de IDataObject.SetData, puis ... –

17

Il folie de tenter de le faire. Vous ne pouvez pas restaurer fidèlement le presse-papiers à son état antérieur. Il pourrait y avoir des douzaines de formats de données non-rendus présents en utilisant le "rendu différé", et si vous tentez de les rendre tous, l'application source sera à court de ressources. C'est comme marcher dans un restaurant et dire «donne-moi un de tout». Supposons que l'utilisateur ait sélectionné 500 lignes x 100 colonnes dans Excel et qu'il les ait copiées dans le Presse-papiers. Excel "annonce" qu'il peut produire ces données dans environ 25 formats différents, y compris Bitmap. Une fois que vous l'avez collé en tant que bitmap, vous forcez Excel à le rendre en tant que bitmap. C'est 50000 cellules, et serait un bitmap d'environ 10 000 x 15 000 pixels. Et vous attendez que l'utilisateur attende pendant que Excel tousse, avec 24 autres formats? Pas faisable.

En outre, vous allez déclencher des événements WM_DrawClipboard, ce qui aura un impact sur les autres visualiseurs de Presse-papiers.

Abandonnez.

+5

"Programmes ne doivent pas transférer des données dans notre hors du presse-papiers sans une instruction explicite de l'utilisateur." - Charles Petzold, Programmation Windows 3.1, Microsoft Press, 1992 –

+0

Ce serait pourquoi la seule fois que j'ai jamais écrit Manipulation de presse-papiers code était lors de l'implémentation de Couper, Copier et Coller dans un menu dans une application .NET. – Powerlord

+0

Je n'ai jamais eu l'intention de rendre toutes les données sauvegardées. La quantité de données récupérées en utilisant le CTRL-C est à peu près la longueur d'une phrase dans le texte. J'espérais un moyen de remettre le contenu original du presse-papiers après avoir utilisé le presse-papiers pour mes propres besoins. Est-il même possible de restaurer le presse-papiers sans obtenir une erreur «impossible d'ouvrir le presse-papiers» dans ce scénario? – gtaborga

Questions connexes