如何保存剪贴板的副本然后恢复到原来的状态?

发布于 2024-08-21 06:18:34 字数 447 浏览 5 评论 0原文

我通过模拟突出显示和复制文本所需的按键来读取文本框中的单词。完成后,我希望剪贴板与我找到它时的样子一模一样。

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

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

但这似乎不起作用。看来你可以专门尝试文本、音频、图片等,然后相应地保存它们。 (我猜“数据对象”也是像我的示例中那样专门化的,我希望它是通用的。)

我不希望对每种可能类型的剪贴板数据都使用案例,这样既更简洁又确保我无论格式如何,都不会丢失数据。

有什么技巧可以抓取所有剪贴板然后恢复它吗?

I'm reading words in a text box by simulating the key presses required to highligh and copy the text. When I'm done, I want the clipboard to be exactly how I found it.

I was hoping I'd be able to do something like this:

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

But that doesn't seem to work. It looks like you can go the route of specifically trying for text, audio, pictures, etc. and then saving them accordingly. (I guess 'data object' is specialized like that in my example too, I was hoping it was generic.)

I'd prefer not to use cases for every possible type of clipboard data, both to be more concise and to make sure I never lose the data regardless of format.

Any tips for grabbing any and all of the clipboard and then restoring it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

昇り龍 2024-08-28 06:18:34

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

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

Do not use the clipboard unless directly instructed to do so by the logged-on user. It's not for general application storage - it's for the user to use for what they want to clip.

If you want to get text from an arbitrary textbox, locate the window (in the Win32) sense and send an EM_GETTEXT Win32 message.

花开柳相依 2024-08-28 06:18:34

下面的文章介绍了一些用于备份和恢复剪贴板的代码。它的内容比人们想象的要多,所以我不会在这里重新发布代码。

C# 中的剪贴板备份

The following article presents some code to backup and restore the Clipboard. There's more to it than one might imagine, so I won't repost the code here.

Clipboard Backup In C#

梦里梦着梦中梦 2024-08-28 06:18:34

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

“如果没有用户的明确指示,程序不应将数据从剪贴板传输到我们的系统中。”
— Charles Petzold,《Windows 3.1 编程》,微软出版社,1992 年

It is impossible to fully restore the clipboard in cases where delayed rendering is used, or where the clipboard data actually contains pointers back into the local program that are not intended for other programs to use them (dumb, but I've seen it). Consider the classic example of Excel, using delayed rendering to offer the same selection in dozens of different formats, including hazardous ones like Bitmap and HTML (could consume hundreds of MB and several minutes of clock time for rendering, if thousands of cells are copied).
And then there is the whole situation of other clipboard viewers reacting to your clipboard manipulations. They'll get duplicate data, altered data, or notification that the clipboard has been erased.
I think this sums it up best:

“Programs should not transfer data into our out of the clipboard without an explicit instruction from the user.”
— Charles Petzold, Programming Windows 3.1, Microsoft Press, 1992

隔岸观火 2024-08-28 06:18:34

我已经用 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;
}

希望这有帮助!

I've implement one sample with 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;
}

Hope this helps!

一生独一 2024-08-28 06:18:34

如果我处于您的位置,我会考虑恢复剪贴板的要求。通常情况下,剪贴板上的数据量相对较小(一段文本、来自网站的图像等),但时不时地您会遇到这样的情况:用户已在剪贴板上放置了大量数据,可能是不久前的数据,也可能不再需要。您的应用程序必须足够强大,能够在操作生命周期内临时存储所有数据。我个人认为这可能不值得付出努力,尽管你比我更了解情况。

简而言之,不要。完成后只需使用 Clipboard.Clear(); 清除剪贴板即可。

I'd consider the requirement for restoring the clipboard at all, if I were in your position. More often than not, the amount of data on the clipboard is going to be relatively small (a block of text, an image from a website, something like that), but every now and then you'll come across a situation where the user has placed a large amount of data on the clipboard, possibly some time ago, and possibly no longer required. Your app will have to be robust enough to cope with temporarily storing all that data during the lifetime of your operation. I personally don't think it is likely to be worth the effort, although you know the situation better than I could.

In short, don't. Just clear the clipboard with Clipboard.Clear(); after you're done.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文