Как я копирую и восстанавливаю системный буфер обмена в C#?

Я приложу все усилия для объяснения подробно, чего я пытаюсь достигнуть.

Я использую C# с дескрипторами окна IntPtr для выполнения операции копии CTRL-C на внешнем приложении из моего собственного приложения C#. Я должен был сделать это, потому что не было никакого способа получить доступ к тексту непосредственно с помощью GET_TEXT. Я затем использую текстовое содержание той копии в рамках моего приложения. Проблема здесь состоит в том, что я теперь перезаписал буфер обмена.

То, что я хотел бы смочь сделать:

  1. Скопируйте исходное содержание буфера обмена, который, возможно, был установлен любым приложением кроме моего собственного.
  2. Затем выполните копию и сохраните значение в мое приложение.
  3. Затем восстановите исходное содержание буфера обмена так, чтобы у пользователя все еще был доступ к его исходным данным буфера обмена.

Это - код, который я попробовал до сих пор:

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? Кто-либо знает о лучшем способе скопировать и восстановить системный буфер обмена?

14
задан Ben Aaronson 3 July 2014 в 15:51
поделиться

2 ответа

Глупо пытаться это сделать. Вы не можете точно восстановить буфер обмена до его предыдущего состояния. Могут существовать десятки форматов необработанных данных, использующих «отложенный рендеринг», и если вы попытаетесь отобразить их все, у исходного приложения будут исчерпаны ресурсы. Это как войти в ресторан и сказать: «Дай мне все».

Предположим, что пользователь выбрал в Excel 500 строк x 100 столбцов и скопировал их в буфер обмена. Excel «рекламирует», что может создавать эти данные примерно в 25 различных форматах, включая Bitmap. Вставив его как растровое изображение, вы заставляете Excel визуализировать его как растровое изображение. Это 50000 ячеек, и это будет растровое изображение размером примерно 10 000 x 15 000 пикселей. И вы ожидаете, что пользователь будет ждать, пока Excel откажется от этого, наряду с 24 другими форматами? Неосуществимо.

Кроме того, вы собираетесь запускать события WM_DrawClipboard, которые повлияют на другие программы просмотра буфера обмена.

Сдавайтесь.

18
ответ дан 1 December 2019 в 12:13
поделиться

Вы можете сохранить содержимое буфера обмена в словаре, а затем восстановить его:

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);
6
ответ дан 1 December 2019 в 12:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: