将原始剪贴板与文本或图像一起保存,稍后在C#中恢复 [英] Save original clipboard with text or image and restore it later in C#

查看:37
本文介绍了将原始剪贴板与文本或图像一起保存,稍后在C#中恢复的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个C#WinForms剪贴板管理器,它可以记住最后X个剪贴板条目,如果它包含图像或文本(不是文件、流或其他奇特的东西)。然后我希望以后能够恢复剪贴板,这样我就可以粘贴原始文本或图像。我的问题是,即使我将剪贴板复制为IDataObject,之后我也无法还原它--至少不是对所有应用程序?

为了测试它,我创建了以下非常简单的代码:

// Get data object from clipboard 
IDataObject clipboardObject = Clipboard.GetDataObject();

// Set the exact same data object to the clipboard
Clipboard.SetDataObject(clipboardObject);

我为此列出了两个测试用例--一个写字板文件和一个Word文件。两者都带有简单的格式化文本(例如彩色编码或斜体),因此可以看到它不仅仅是纯文本。

如果我在启动我的简单应用程序之前从写字板复制文本,则可以使用格式再次粘贴该文本-没有问题。

Word中执行相同操作后,它会粘贴一些奇怪的东西--空文件对象或类似对象!?

word的左下角写着:

双击或双Tab键打开Microsoft Word文档

它现在似乎将剪贴板视为文件指针或类似的东西?如果我双击该区域,它实际上会打开一个新的Word文件!?我不明白吗?

我已经检查过C# Backing Up And Restoring Clipboard,我可以承认,实际上谁是一模一样的,但我也尝试了其中的各种建议,至少没有一项对我有效?我希望10年后会有更好的答案?;-)

仅从对象还原文本格式也不起作用,因为如果对象为空,则剪贴板将起作用(不粘贴任何内容)。

有人有还原剪贴板(文本和图像方面的)的经验吗?

我的目标是将剪贴板历史记录保存在例如Dictionary中,然后向上/向下遍历,这样我就可以恢复我需要的剪贴板历史记录。


解决方案

根据@jimi下面的评论,这确实解决了我的问题:

// Set the exact same data object to the clipboard
Clipboard.SetDataObject(clipboardObject, true);

据我所知,如果copy参数未设置或设置为false,则它实际上将引用指针。如果此参数设置为true,则它将设置剪贴板中的实际数据,并且即使我的应用程序存在,数据也将保留在那里。


更新-如何使用SetText

保存/恢复已放入剪贴板的对象

虽然我已经回答了这个主要问题,但我仍然有一个挑战,我认为它也可以在这里讨论。我希望存储剪贴板对象,以便以后可以获取它们--可能在Dictionary中。然后我创建了这个PoC,它似乎在许多情况下确实有效,但如果数据作为SetText存储到剪贴板,那么在恢复和粘贴时,它似乎返回一个空剪贴板?

如果您在此处查看此代码,则我正在恢复手动设置的剪贴板-它不会粘贴任何内容,并且剪贴板看起来是空的:

        // Define variables
        Dictionary<int, object> clipboardObjects = new Dictionary<int, object>();
        IDataObject clipboardObject;

        // Get formatted text content from clipboard (copied from Word)
        clipboardObject = Clipboard.GetDataObject();

        // Add clipboard object in the first [0] dictionary
        clipboardObjects.Add(0, clipboardObject);

        // Put new content to the clipboard - just to show we can destroy it before restoring again
        Clipboard.SetText("Test, to alter the clipboard");

        // Add clipboard object in the second [1] dictionary
        clipboardObject = Clipboard.GetDataObject();
        clipboardObjects.Add(1, clipboardObject);

        // Now restore the second [1] clipboard object - which will result in an empty clipboard
        clipboardObject = (IDataObject)clipboardObjects[1];
        Clipboard.SetDataObject(clipboardObject, true);

上述操作将导致一个空白的剪贴板--或者至少它不会粘贴任何内容。有趣的是,如果我恢复第一个[0]对象(它包含格式化文本),那么它会恢复它,我可以很好地粘贴它!?

为什么无法还原SetText对象?

这种方法不起作用的问题是,我不知道应用程序如何将数据存储到剪贴板。SetText可能是他们存储数据的方式。我已使用SetDataObject而不是SetText对其进行了测试,然后我可以恢复它。

推荐答案

因为没有人回答这个问题,所以我会自己做,就像我根据@jimi的评论想出了解决方案一样。我的答案没有100%回答我的问题,但它解决了我的问题。我怀疑它是否适用于所有东西,但至少它适用于我的基本用法,即只关注剪贴板上的文本和图像。

我已经使用写字板Word在Windows 10中测试了以下代码,它可以工作,但当然,在您的场景中可能会有不同的情况或工作方式,但也许它可以为有类似问题的人提供一些提示:-)

代码将从剪贴板获取相关格式(格式化的文本或图像),并将其保存到ListDictionary。之后,您可以使用剪贴板执行任何操作,然后可以再次检索和还原剪贴板。

using System.Windows.Forms;
using System.Collections.Generic;

// Define variables
int key = 0;
IDataObject clipboardObject;
SortedList<int, Dictionary<string, object>> clipboardOriginals = new SortedList<int, Dictionary<string, object>>(); // can be referred by integer and can contain clipboard objects

// ---------
// Save formatted clipboard to a list of dictionaries

// Get the clipboard object
clipboardObject = Clipboard.GetDataObject();

// Walk through all (relevant) clipboard formats and save them in a new object
var formats = clipboardObject.GetFormats(false);
Dictionary<string, object> clipboardFormats = new Dictionary<string, object>();
foreach (var format in formats)
{
    if (
        format.Contains("Text") ||
        format.Contains("Hyperlink") ||
        format.Contains("Bitmap")
    )
    {
        // Add the clipboard format to the clipboard object
        clipboardFormats.Add(format, clipboardObject.GetData(format));
    }
}

// Save the clipboard formats to the dictionary containing all originals
clipboardOriginals.Add(key, clipboardFormats);

// ---------
// Now do whatever you want with the clipboard
Clipboard.Clear();
Clipboard.SetText("Cleared");

// ---------
// Restore the (semi) original clipboard - at least the relevant formats we have saved

DataObject data = new DataObject();
foreach (KeyValuePair<string, object> kvp in clipboardOriginals[key])
{
    if (kvp.Value != null)
    {
        data.SetData(kvp.Key, kvp.Value);
    }
}

// Copy the saved formats to the clipboard
Clipboard.SetDataObject(data, true);

// Try now to paste the clipboard - it should contain the original formatting (hopefully)? :-)

这可能根本不是防弹的,但到目前为止,它似乎对我和我的用法都有效。

这篇关于将原始剪贴板与文本或图像一起保存,稍后在C#中恢复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆