如何保存剪贴板的副本然后还原到它?

时间:2010-02-11 08:52:20

标签: c# clipboard

我正在通过模拟高光和复制文本所需的按键来读取文本框中的文字。当我完成后,我希望剪贴板正是我找到它的方式。

我希望能够做到这样的事情:

IDataObject clipboardBackup = Clipboard.GetDataObject();
Clipboard.Clear();
//Save other things into the clipboard here, etc//
Clipboard.SetDataObject(clipboardBackup);

但这似乎不起作用。看起来您可以专门尝试文本,音频,图片等,然后相应地保存它们。 (我猜'数据对象'在我的例子中也是专门的,我希望它是通用的。)

我不想为每种可能类型的剪贴板数据使用案例,既要更简洁,又要确保不管格式如何都不会丢失数据。

抓取任何和所有剪贴板然后恢复它的任何提示?

5 个答案:

答案 0 :(得分:3)

除非登录用户直接指示,否则请勿使用剪贴板。它不适用于一般应用程序存储 - 用户可以使用它们想要剪辑的内容。

如果要从任意文本框中获取文本,请找到窗口(在Win32中)并发送EM_GETTEXT Win32消息。

答案 1 :(得分:3)

以下文章介绍了一些备份和还原剪贴板的代码。还有比人们想象的更多,所以我不会在这里重新发布代码。

Clipboard Backup In C#

答案 2 :(得分:2)

在使用延迟渲染的情况下,或者剪贴板数据实际上包含指向本地程序的指针而不是其他程序使用它们时,无法完全恢复剪贴板(愚蠢,但我见过它)。考虑Excel的经典示例,使用延迟渲染以几十种不同的格式提供相同的选择,包括Bitmap和HTML等危险的格式(如果复制了数千个单元格,可能会消耗数百MB和几分钟的时间进行渲染) 。 然后,其他剪贴板查看器的整个情况会对剪贴板操作做出反应。他们将获得重复数据,更改数据或剪贴板已被删除的通知 我认为这总结得最好:

“如果没有用户的明确指示,程序不应将数据传输到剪贴板中。”
- Charles Petzold,Windows 3.1编程,Microsoft Press,1992

答案 3 :(得分:1)

我用c ++实现了一个样本。

#include "stdafx.h"
#include "TestClip.h"
#include <Windows.h>
#include <queue>

using namespace std;

typedef struct
{
UINT format;
LPVOID content;
SIZE_T size;
} ClipBoardItem;

void InspectClipboard()
{
UINT uFormat = 0;
HGLOBAL hglb;
LPVOID hMem;
float totalSize = 0;

if (!OpenClipboard(NULL))
{
    cout << "Open clipboard failed!" << endl;
    system("pause");
    return;
}

int countFormat = CountClipboardFormats();
cout << "Clipboard formats count: " << countFormat << endl;

uFormat = EnumClipboardFormats(uFormat);
while (uFormat)
{
    cout << "Clipboard format:" << uFormat;
    hglb = GetClipboardData(uFormat);
    if (hglb != NULL)
    {
        hMem = GlobalLock(hglb);
        SIZE_T size = GlobalSize(hMem);
        cout << ", size:" << size << endl;
        totalSize += size;
        if (hMem != NULL)
        {
            GlobalUnlock(hglb);
        }
    }
    else
    {
        cout << " data is NULL" << endl;
    }
    uFormat = EnumClipboardFormats(uFormat);
}
CloseClipboard();

string unit = "bytes";
if (totalSize >= 1024)
{
    totalSize /= 1024;
    unit = "KB";
}
if (totalSize >= 1024)
{
    totalSize /= 1024;
    unit = "MB";
}
if (totalSize >= 1024)
{
    totalSize /= 1024;
    unit = "GB";
}
cout << "Total size is: " << totalSize << " " << unit.data() << endl;
}

queue<ClipBoardItem> BackupClipboard()
{
queue<ClipBoardItem> clipQueue;
UINT uFormat = 0;
HGLOBAL hglb;
LPTSTR lptstr;
LPVOID hMem;
if (!OpenClipboard(NULL))
{
    cout << "Open clipboard failed" << endl;
    return clipQueue;
}

uFormat = EnumClipboardFormats(uFormat);
while (uFormat)
{
    cout << "Backup clipboard format:" << uFormat << endl;
    hglb = GetClipboardData(uFormat);
    if (hglb != NULL)
    {
        hMem = GlobalLock(hglb);
        SIZE_T size = GlobalSize(hMem);
        if (size > 0)
        {
            ClipBoardItem clipitem;
            clipitem.format = uFormat;
            clipitem.content = malloc(size);
            clipitem.size = size;
            memcpy(clipitem.content, hMem, size);
            clipQueue.push(clipitem);
        }

        if (hMem != NULL)
        {
            GlobalUnlock(hglb);
        }
    }
    uFormat = EnumClipboardFormats(uFormat);
}
EmptyClipboard();
CloseClipboard();
cout << "Clipboard has been cleaned" << endl;
return clipQueue;
}

void RestoreClipboard(queue<ClipBoardItem> clipQueue)
{
if (!OpenClipboard(NULL)) return;

while (!clipQueue.empty())
{
    ClipBoardItem clipitem = clipQueue.front();
    HGLOBAL hResult = GlobalAlloc(GMEM_MOVEABLE, clipitem.size);
    if (hResult == NULL)
    {
        cout << "GlobalAlloc failed" << endl;
        clipQueue.pop();
        continue;
    }
    memcpy(GlobalLock(hResult), clipitem.content, clipitem.size);
    GlobalUnlock(hResult);
    if (SetClipboardData(clipitem.format, hResult) == NULL) {
        cout << "Set clipboard data failed" << endl;
    }
    cout << "Resotred clipboard format:" << clipitem.format << endl;
    GlobalFree(hResult);
    free(clipitem.content);
    clipQueue.pop();
}
CloseClipboard();
}

int _tmain(int argc, TCHAR* argv [], TCHAR* envp [])
{
InspectClipboard();
cout << "Press any key to backup and empty clipboard" << endl;
system("pause");

queue<ClipBoardItem> clipQueue = BackupClipboard();
InspectClipboard();
cout << "Press any key to restore clipboard" << endl;
system("pause");
RestoreClipboard(clipQueue);
cout << "Clipboard has been restored" << endl;
system("pause");
InspectClipboard();
system("pause");
return 0;
}

希望这有帮助!

答案 4 :(得分:-1)

如果我在你的位置,我会考虑恢复剪贴板的要求。通常情况下,剪贴板上的数据量将相对较小(一个文本块,一个来自网站的图像,类似的东西),但是偶尔你会遇到一个用户的情况可能在一段时间之前已经在剪贴板上放置了大量数据,并且可能不再需要。您的应用程序必须足够强大,以便在您的操作生命周期内临时存储所有数据。我个人并不认为这可能是值得的,尽管你比我更了解情况。

总之,不要。完成后,只需使用Clipboard.Clear();清除剪贴板。