How do I save a copy of the clipboard and then revert back to it?

为君一笑 提交于 2019-12-05 17:52:18

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.

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#

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

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!

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.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!