2009-09-03 6 views
5

J'essaie d'écrire une petite application qui doit utiliser le presse-papiers pour certaines fonctionnalités. Puisque je ne veux pas écraser les données de l'utilisateur actuellement dans le presse-papiers, j'ai décidé de l'enregistrer en mémoire, de faire mon travail et de le réécrire. Le code ci-dessous est une application de console qui est un exemple de ce que j'essaie de faire.Étrangeté avec accès au presse-papiers

Le problème que je rencontre est la restauration de l'état. Si je copie quelque chose dans le presse-papiers à partir de Visual Studio avant d'exécuter l'application, il y a un total de six objets dans le presse-papiers (différents formats de chaîne et une locale) qui sont tous mis dans le cache. Une fois que je les restaure, seuls les paramètres régionaux sont dans le presse-papiers et il apparaît que chaque appel à SetData() écrase le dernier. (par la façon dont SetDataObject ne semble pas être l'inverse de GetDataObject donc je ne peux pas l'utiliser)

Des idées sur comment je peux stocker l'état du presse-papiers et le restaurer plus tard?

[STAThread] 
    static void Main(string[] args) 
    { 
     //Store the old clipboard data 
     Dictionary<string, object> clipboardCache = new Dictionary<string, object>(); 

     IDataObject clipboardData = Clipboard.GetDataObject(); 

     foreach (string format in clipboardData.GetFormats()) 
     { 
      clipboardCache.Add(format, clipboardData.GetData(format)); 
     } 

     Clipboard.SetText("Hello world!"); 

     string value = Clipboard.GetText(); 

     Console.WriteLine(value); 

     //Clear the clipboard again and restore old data 
     Clipboard.Clear(); 

     foreach (KeyValuePair<string, object> valuePair in clipboardCache) 
     { 
      Clipboard.SetData(valuePair.Key, valuePair.Value); 
      Thread.Sleep(100); 
     } 

     Console.ReadLine(); 
    } 
+0

Utilisez-vous un plugin pour plusieurs presse-papiers comme ClipX? – TheVillageIdiot

+0

L'extrait de code a résolu mon problème - complètement différent du vôtre - mais google m'amène ici, donc je posterai les détails ici: Pour toute personne ayant des difficultés à accéder au presse-papiers de Windows à partir d'une application de console, "méthode avec l'attribut" [STAThread] "! : D – BrainSlugs83

Répondre

5

Le presse-papiers Windows ne contient qu'un seul objet à la fois. Mais il existe plusieurs formats disponibles (par exemple RTF, texte, HTML) à partir de cet objet. Je pense que vous le rendez trop compliqué et votre code devrait être quelque chose comme ceci:

//Store the old clipboard data 
IDataObject clipboardData = Clipboard.GetDataObject(); 

Clipboard.SetText("Hello world!"); 

string value = Clipboard.GetText(); 
Console.WriteLine(value); 

//Clear the clipboard again and restore old data 
Clipboard.Clear(); 
Clipboard.SetDataObject(clipboardData); 

Console.ReadLine(); 
+1

Comme je l'ai dit dans ma question, je ne pensais pas que SetDatObject fonctionnait parce qu'il ne semblait pas accepter un IDataObject et qu'il laissait le presse-papiers vide , Mais je me trompais.Par défaut, il ne conserve que les données dans le presse-papiers jusqu'à la fermeture de l'application. Après avoir lu un peu autour de moi j'ai trouvé que votre code fonctionne en remplaçant SetDataObject (clipboardData) avec SetDataObject (clipboardData, true). Merci - je pensais que devrait être simple. –

1

Martin J'ai essayé votre code. J'ai ClipX installé sur mon système. En cours d'exécution lorsque j'exécute votre code, j'obtiens autant d'éléments que dans le cache de ClipX. Mais l'appel Clipboard.GetDataObject() renvoie uniquement le dernier objet. Alors qu'est-ce qui se passe est que lorsque vous appelez cette boucle:

foreach (string format in clipboardData.GetFormats()) 
{ 
    clipboardCache.Add(format, clipboardData.GetData(format)); 
} 

il retourne le format pour tous les objets dans la ClipX et de convertir les données renvoyées par

IDataObject clipboardData = Clipboard.GetDataObject(); 

Donc en fait lorsque vous exécutez cette boucle

foreach (KeyValuePair<string, object> valuePair in clipboardCache) 
{ 
    Clipboard.SetData(valuePair.Key, valuePair.Value); 
    Thread.Sleep(100); 
} 

vous avez un seul objet qui est en cours de définition dans le Presse-papiers.

Deuxièmement, lors de l'utilisation de Clipboard.SetData(format,object), l'écrasement d'un objet plus ancien par un nouveau est un comportement normal et non normal. Si vous créez une sorte de presse-papiers à entrées multiples, vous devez intercepter copier et coller les appels système et conserver l'objet dans la mémoire ou le disque de votre programme. Vous ne pouvez pas compter sur le presse-papiers par défaut.

+1

Merci pour la réponse. Je n'utilise aucune extension de presse-papiers et je ne cherche qu'à enregistrer un élément, mais si vous copiez du texte à partir de Visual Studio (par exemple), il y aura plusieurs éléments stockés dans le presse-papiers - une représentation sous forme de chaîne du texte, une version RTF, les paramètres régionaux - en tout mon clipboardData a six formats, et je veux mettre tous les six objets dans le presse-papiers. Pouvez-vous essayer de copier du texte à partir de Visual Studio? Combien de résultats obtenez-vous de clipboardData.GetFormats() alors? –

+1

Juste pour ajouter - Je pensais aussi que vous ne pouviez stocker qu'un seul élément dans le presse-papiers, mais à partir d'aujourd'hui, vous pouvez avoir un seul élément * par * format. Je serais également intéressé de savoir si je n'ai pas raison à ce sujet ... –