Как сделать резервную копию и восстановить системный буфер обмена в C #? - PullRequest
13 голосов
/ 05 апреля 2010

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

Я использую 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
    }
}

Я использую System.Windows.Clipboard, а не System.Windows.Forms.Clipboard. Причиной этого было то, что когда я выполнял CTRL-C, класс Clipboard из System.Windows.Forms не возвращал никаких данных, а системный буфер обмена.

Я изучил некоторые низкоуровневые вызовы user32, такие как OpenClipboard, EmptyClipboard и CloseClipboard, надеясь, что они помогут мне в этом, но до сих пор я продолжаю получать исключения COM при попытке восстановления.

Я подумал, что, возможно, это связано с параметром OpenClipboard, который ожидает дескриптор окна IntPtr приложения, которое хочет получить контроль над буфером обмена. Поскольку я упомянул, что мое приложение не имеет графического интерфейса, это проблема. Я не был уверен, что пройти здесь. Может быть, кто-то может пролить свет на это?

Я неправильно использую класс Clipboard? Есть ли четкий способ получить дескриптор окна IntPtr приложения без графического интерфейса? Кто-нибудь знает лучший способ резервного копирования и восстановления системного буфера обмена?

Ответы [ 2 ]

19 голосов
/ 05 апреля 2010

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

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

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

Сдайся.

6 голосов
/ 05 апреля 2010

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

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...