Я приложу все усилия для объяснения подробно, чего я пытаюсь достигнуть.
Я использую C# с дескрипторами окна IntPtr для выполнения операции копии CTRL-C на внешнем приложении из моего собственного приложения C#. Я должен был сделать это, потому что не было никакого способа получить доступ к тексту непосредственно с помощью GET_TEXT. Я затем использую текстовое содержание той копии в рамках моего приложения. Проблема здесь состоит в том, что я теперь перезаписал буфер обмена.
То, что я хотел бы смочь сделать:
Это - код, который я попробовал до сих пор:
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
}
}
Я использую Систему. Windows. Буфер обмена а не Система. Windows. Формы. Буфер обмена. Причина этого была этим, когда я выполнил CTRL-C, класс Буфера обмена от Системы. Windows. Формы не возвратили данных, но системный буфер обмена сделал.
Я изучил некоторые низкоуровневые user32 вызовы как OpenClipboard, EmptyClipboard и CloseClipboard, надеясь, что они помогут моему сделать это, но до сих пор я продолжаю получать COM-исключения при попытке восстановить.
Я думал, возможно, что это имело отношение к параметру OpenClipboard, который ожидает дескриптор окна IntPtr приложения, которое хочет взять под свой контроль буфер обмена. Так как я упомянул, что мое приложение не имеет GUI, это - проблема. Я не был уверен, что передать сюда. Возможно, кто-то может пролить некоторый свет на это?
Я использую класс Буфера обмена неправильно? Существует ли ясный способ получить дескриптор окна IntPtr приложения без GUI? Кто-либо знает о лучшем способе скопировать и восстановить системный буфер обмена?
Глупо пытаться это сделать. Вы не можете точно восстановить буфер обмена до его предыдущего состояния. Могут существовать десятки форматов необработанных данных, использующих «отложенный рендеринг», и если вы попытаетесь отобразить их все, у исходного приложения будут исчерпаны ресурсы. Это как войти в ресторан и сказать: «Дай мне все».
Предположим, что пользователь выбрал в Excel 500 строк x 100 столбцов и скопировал их в буфер обмена. Excel «рекламирует», что может создавать эти данные примерно в 25 различных форматах, включая Bitmap. Вставив его как растровое изображение, вы заставляете Excel визуализировать его как растровое изображение. Это 50000 ячеек, и это будет растровое изображение размером примерно 10 000 x 15 000 пикселей. И вы ожидаете, что пользователь будет ждать, пока Excel откажется от этого, наряду с 24 другими форматами? Неосуществимо.
Кроме того, вы собираетесь запускать события WM_DrawClipboard, которые повлияют на другие программы просмотра буфера обмена.
Сдавайтесь.
Вы можете сохранить содержимое буфера обмена в словаре, а затем восстановить его:
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);