使用文本或图像保存原始剪贴板,稍后在 C# 中恢复它
Save original clipboard with text or image and restore it later in 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);
我为此准备了两个测试用例 - 一个 Wordpad 文件和一个 Word 文件。两者都带有简单格式的文本 - 例如颜色编码或斜体 - 可以看出它不是纯文本。
如果我从 写字板 复制文本,然后再启动我的简单应用程序,那么我可以再次粘贴该文本,格式正确 - 没问题。
在 Word 中执行相同的操作,然后它会粘贴一些奇怪的东西 - 一个空文件对象或类似的东西!?
在 Word 的左下角写着:
Double-click or double-tab to Open Microsoft Word Document
它现在似乎将剪贴板视为文件指针或类似的东西?如果我双击该区域,它实际上会打开一个新的 Word 文件!?我不明白?
我已经检查过 C# Backing Up And Restoring Clipboard,我可以承认,谁实际上是相同的,但我也尝试了那里的各种建议,但至少没有一个对我有用?我希望 10 年后可能会有更好的答案? ;-)
仅从对象恢复文本格式也不起作用,因为剪贴板将在它为空时起作用(它不会粘贴任何内容)。
有没有人有恢复剪贴板的经验(在文本和图像方面)?
我的目标是将剪贴板历史保存在例如一个Dictionary
然后遍历up/down,这样我就可以恢复我需要的
解决方案
根据下面@Jimi 的评论,这确实解决了我的问题:
// Set the exact same data object to the clipboard
Clipboard.SetDataObject(clipboardObject, true);
据我了解,如果 copy
参数未设置或设置为 false
,那么它实际上将引用指针。如果此参数设置为 true
,那么它将在剪贴板中设置实际数据,即使我的应用程序存在,数据仍将保留在那里。
更新 - 如何 save/restore 已使用 SetText
放入剪贴板的对象
虽然我已经解决了这个问题的主要问题,但我仍然面临挑战,我认为它也可以在这里解决。我想存储剪贴板对象,以便稍后获取它们 - 可能在 Dictionary
中。然后我创建了这个 PoC,它似乎在很多情况下都有效,但是如果数据以 SetText
的形式存储到剪贴板,那么在恢复和粘贴时它似乎 return 是一个空的剪贴板?
如果您在此处查看此代码,那么我正在恢复我手动设置的剪贴板 - 它不会粘贴任何内容并且剪贴板看起来是空的:
// 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% 的问题,但它解决了我的问题。我怀疑它是否适用于所有情况,但至少它适用于我对它的基本使用,它只关注剪贴板中的文本和图像。
我已经在 Windows 10 中使用 Wordpad 和 Word 测试了以下代码,它可以工作,但当然可以在你的场景中改变或工作不同,但也许它可以为有类似问题的人提供一些提示:-)
该代码将从剪贴板中抓取相关格式(带格式的文本或图像)并将其保存到 Dictionary
的 List
。之后你可以对剪贴板做任何你想做的事,稍后你可以再次检索和恢复剪贴板。
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# WinForms 剪贴板管理器,它可以记住最后的 X 剪贴板条目,如果它包含图像或文本(不是文件、流或其他花哨的东西)。然后我希望以后能够恢复剪贴板,所以我可以粘贴原始文本或图像。 我的问题是,即使我将剪贴板复制为 IDataObject
,之后我也无法恢复它 - 至少不是对所有应用程序都如此?
为了测试它,我创建了这个非常简单的代码:
// Get data object from clipboard
IDataObject clipboardObject = Clipboard.GetDataObject();
// Set the exact same data object to the clipboard
Clipboard.SetDataObject(clipboardObject);
我为此准备了两个测试用例 - 一个 Wordpad 文件和一个 Word 文件。两者都带有简单格式的文本 - 例如颜色编码或斜体 - 可以看出它不是纯文本。
如果我从 写字板 复制文本,然后再启动我的简单应用程序,那么我可以再次粘贴该文本,格式正确 - 没问题。
在 Word 中执行相同的操作,然后它会粘贴一些奇怪的东西 - 一个空文件对象或类似的东西!?
在 Word 的左下角写着:
Double-click or double-tab to Open Microsoft Word Document
它现在似乎将剪贴板视为文件指针或类似的东西?如果我双击该区域,它实际上会打开一个新的 Word 文件!?我不明白?
我已经检查过 C# Backing Up And Restoring Clipboard,我可以承认,谁实际上是相同的,但我也尝试了那里的各种建议,但至少没有一个对我有用?我希望 10 年后可能会有更好的答案? ;-)
仅从对象恢复文本格式也不起作用,因为剪贴板将在它为空时起作用(它不会粘贴任何内容)。
有没有人有恢复剪贴板的经验(在文本和图像方面)?
我的目标是将剪贴板历史保存在例如一个Dictionary
然后遍历up/down,这样我就可以恢复我需要的
解决方案
根据下面@Jimi 的评论,这确实解决了我的问题:
// Set the exact same data object to the clipboard
Clipboard.SetDataObject(clipboardObject, true);
据我了解,如果 copy
参数未设置或设置为 false
,那么它实际上将引用指针。如果此参数设置为 true
,那么它将在剪贴板中设置实际数据,即使我的应用程序存在,数据仍将保留在那里。
更新 - 如何 save/restore 已使用 SetText
虽然我已经解决了这个问题的主要问题,但我仍然面临挑战,我认为它也可以在这里解决。我想存储剪贴板对象,以便稍后获取它们 - 可能在 Dictionary
中。然后我创建了这个 PoC,它似乎在很多情况下都有效,但是如果数据以 SetText
的形式存储到剪贴板,那么在恢复和粘贴时它似乎 return 是一个空的剪贴板?
如果您在此处查看此代码,那么我正在恢复我手动设置的剪贴板 - 它不会粘贴任何内容并且剪贴板看起来是空的:
// 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% 的问题,但它解决了我的问题。我怀疑它是否适用于所有情况,但至少它适用于我对它的基本使用,它只关注剪贴板中的文本和图像。
我已经在 Windows 10 中使用 Wordpad 和 Word 测试了以下代码,它可以工作,但当然可以在你的场景中改变或工作不同,但也许它可以为有类似问题的人提供一些提示:-)
该代码将从剪贴板中抓取相关格式(带格式的文本或图像)并将其保存到 Dictionary
的 List
。之后你可以对剪贴板做任何你想做的事,稍后你可以再次检索和恢复剪贴板。
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)? :-)
这可能根本不是防弹的,但到目前为止它似乎对我和我的用法有用。