2009-09-03 20 views
5

Próbuję napisać małą aplikację, która musi korzystać ze schowka dla niektórych funkcji. Ponieważ nie chcę nadpisywać danych użytkownika znajdujących się w schowku, postanowiłem zapisać go w pamięci, wykonać zadanie, a następnie je zapisać. Poniższy kod to aplikacja konsolowa, która jest prostym przykładem tego, co próbuję zrobić.Dziwność z dostępem do schowka

Problem, który mam, to przywrócenie stanu. Jeśli skopiuję coś do schowka z Visual Studio przed uruchomieniem aplikacji, w schowku znajduje się łącznie sześć obiektów (różne formaty ciągów znaków i ustawienia regionalne), które wszystkie zostaną umieszczone w pamięci podręcznej. Raz je przywracam, chociaż w schowku są tylko ustawienia narodowe i wydaje się, że każde wywołanie SetData() zastępuje ostatnie. (przy okazji SetDataObject nie wydaje się być odwrotnością GetDataObject, więc nie mogę tego po prostu użyć)

Jakieś pomysły, w jaki sposób mogę zapisać stan schowka i przywrócić go później?

[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

Czy używasz wtyczek do wielu obiektów, takich jak ClipX? – TheVillageIdiot

+0

Fragment kodu faktycznie rozwiązał mój problem - zupełnie inny od twojego - ale google poprowadził mnie tutaj, więc opublikuję szczegóły tutaj: Dla każdego, kto ma problemy z dostępem do schowka Windows z aplikacji na konsolę, upewnij się, że udekorowałeś swój "Główny" "metoda z atrybutem" STAThread] "! : D – BrainSlugs83

Odpowiedz

5

Schowek na okna zawiera tylko jeden obiekt naraz. Istnieje jednak wiele dostępnych formatów (np. RTF, Text, HTML) z tego jednego obiektu. Myślę, że robisz to zbyt skomplikowane, a twój kod powinien wyglądać mniej więcej tak:

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

Jak powiedziałem w moim pytaniu nie myślałem, że SetDatObject działał, ponieważ nie wydaje się, aby zaakceptować IDataObject i zostawił puste schowka , ale byłem w błędzie.Domyślnie przechowuje dane tylko w schowku, dopóki aplikacja nie zakończy pracy. Po krótkiej lekturze stwierdziłem, że twój kod działa w zamian za zastąpienie SetDataObject (clipboardData) za pomocą SetDataObject (clipboardData, true). Dzięki - myślałem, że powinno być proste. –

1

Martin Wypróbowałem twój kod. Mam zainstalowany w moim systemie ClipX. Dzięki uruchomieniu, gdy uruchomię Twój kod, otrzymam tyle pozycji, ile jest w pamięci podręcznej ClipX. Jednak wywołanie Clipboard.GetDataObject() zwraca tylko ostatni obiekt. Więc co się dzieje, że po wywołaniu tej pętli:

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

powraca format całego obiektu w ClipX i konwersji danych zwracanych przez

IDataObject clipboardData = Clipboard.GetDataObject(); 

tak faktycznie podczas wykonywania tej pętli

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

Masz tylko jeden obiekt, który jest ustawiony na schowek.

Po drugie, przy użyciu Clipboard.SetData(format,object) nadpisanie starszego obiektu na nowy jest normalnym zachowaniem, a nie normalnym. Jeśli budujesz coś w rodzaju schowka wejściowego, musisz przechwycić kopie i wkleić wywołania systemowe i zatrzymać obiekt w pamięci programu lub na dysku. Nie można polegać na domyślnym schowku.

+1

Dzięki za odpowiedź. W ogóle nie używam żadnych rozszerzeń schowka i chcę tylko zapisać jeden element, ale jeśli skopiujesz tekst z Visual Studio (na przykład), w schowku będzie przechowywanych wiele elementów - ciąg znaków w tekście, wersja RTF, ustawienie regionalne - w sumie moja clipboardData ma sześć formatów i chcę umieścić wszystkie sześć obiektów z powrotem w schowku. Czy możesz spróbować skopiować tekst z Visual Studio? Ile wyników otrzymasz od clipboardData.GetFormats()? –

+1

Po prostu do dodania - myślałem również, że można przechowywać tylko jeden przedmiot w schowku, ale teraz z nim się z nim obchodzimy, że możesz mieć jeden przedmiot * na * format. Byłbym także zainteresowany, aby wiedzieć, czy nie mam rację w tym ... –

Powiązane problemy