用C ++将结构保存到剪贴板

时间:2014-12-05 17:37:08

标签: c++ string winapi struct clipboard

我的C ++代码中有这个结构:

struct sData
{
    DWORD Number;
    int CurrentNumber;
    bool GameOver;
};

我需要将它作为一个进程的结构保存到剪贴板。从其他过程我需要再次加载它作为结构。我可以使用Cstrings / strings轻松完成,但不能使用结构。你对我有什么建议?

这是我将Cstring设置为剪贴板的方法:

bool SetText(CString text)
    {
        CString  source;
        source = text;
        //put your text in source
        if (OpenClipboard(NULL))
        {
            HGLOBAL clipbuffer;
            char * buffer;
            EmptyClipboard();
            clipbuffer = GlobalAlloc(GMEM_DDESHARE, source.GetLength() + 1);
            buffer = (char*)GlobalLock(clipbuffer);
            strcpy(buffer, LPCSTR(source));
            GlobalUnlock(clipbuffer);
            SetClipboardData(CF_TEXT, clipbuffer);
            CloseClipboard();
            return true;
        }
        else
        {
            return false;
        }
    }

这是吸气剂:

std::string GetText(void) const
    {
        return (const char*)GetClipboardData(CF_TEXT);
    }

1 个答案:

答案 0 :(得分:4)

您需要注册自己的剪贴板格式,然后才能按原样存储struct数据。

static UINT CF_MYSTRUCTDATA = RegisterClipboardFormat(TEXT("MyStructData"));

#pragma pack(push, 1)
struct sData
{
    DWORD Number;
    int CurrentNumber;
    bool GameOver;
};
#pragma pack(pop)

bool SetData(const sData &data)
{
    if (CF_MYSTRUCTDATA == 0)
        return false;

    bool bOK = false;
    if (OpenClipboard(NULL))
    {
        if (EmptyClipboard())
        {
            HGLOBAL clipbuffer = GlobalAlloc(GMEM_MOVEABLE, sizeof(sData));
            if (clipbuffer)
            {
                sData *buffer = (sData*) GlobalLock(clipbuffer);
                if (buffer)
                {
                    *buffer = data;
                    GlobalUnlock(clipbuffer);
                    bOK = SetClipboardData(CF_MYSTRUCTDATA, clipbuffer);
                }
                if (!bOK)
                    GlobalFree(clipbuffer);
            }
        }
        CloseClipboard();
    }

    return bOK;
}

bool GetData(sData &data) const
{
    if (CF_MYSTRUCTDATA == 0)
        return false;

    bool bOk = false;
    if (OpenClipboard(NULL))
    {
        HANDLE clipbuffer = GetClipboardData(CF_MYSTRUCTDATA);
        if (clipbuffer)
        {
            sData *buffer = (sData*) GlobalLock(clipbuffer);
            if (buffer)
            {
                data = *buffer;
                GlobalUnlock(clipbuffer);
                bOK = true;
            }
        }
        CloseClipboard();
    }
    return bOK;
}

或者,使用一些C ++ RAII包装器:

struct Clipboard
{
    Clipboard(HWND hWnd = NULL)
    {
        if (!OpenClipboard(hWnd))
            throw std::runtime_error("Error opening clipboard");
    }

    ~Clipboard()
    {
        CloseClipboard();
    }

    void Empty()
    {
        if (!EmptyClipboard())
            throw std::runtime_error("Error emptying clipboard");
    }

    template<typename T>
    struct DataBuffer
    {
        HGLOBAL _hmem;
        bool _free;

        struct Lock
        {
            DataBuffer& _buffer;
            T* _data;

            Lock(DataBuffer &buffer)
                : _buffer(buffer), _locked(false)
            {
                _data = (T*) GlobalLock(_buffer.Get());
                if (!_data)
                    throw std::runtime_error("Error locking memory");
            }

            ~Lock()
            {
                GlobalUnlock(_buffer.Get());
            }

            T& Data() { return *_data; }
        };

        DataBuffer(const T &data)
            : _hmem(NULL), _free(true)
        {
            _hmem = GlobalAlloc(GMEM_MOVEABLE, sizeof(T));
            if (!_hmem)
                throw std::runtime_error("Error allocating memory");
            Lock(*this).Data() = data;
        }

        DataBuffer(HGLOBAL hmem)
            : _hmem(mem), _free(false)
        {
            if (GlobalSize(_hmem)) < sizeof(T))
                throw std::runtime_error("Bad memory size");
        }

        ~DataBuffer()
        {
            if ((_hmem) && (_free))
                GlobalFree(_hmem);
        }

        HGLOBAL Release()
        {
            HGLOBAL tmp = _hmem;
            _hmem = NULL;
            return tmp;
        }

        HGLOBAL Get()
        {
            return _hmem;
        }

        void Copy(T &data)
        {
            data = Lock(*this).Data();
        }
    };

    template<typename T>
    void SetData(UINT format, const T &data)
    {
        DataBuffer<T> buffer(data);
        if (!SetClipboardData(format, buffer.Get()))
            throw std::runtime_error("Error setting clipboard data");
        buffer.Release();
    }

    template<typename T>
    void GetData(UINT format, T &data)
    {
        DataBuffer<T> buffer(GetClipboardData(format));
        if (!buffer.Get())
            throw std::runtime_error("Error getting clipboard data");
        buffer.Copy(data);
    }
};

bool SetData(const sData &data)
{
    if (CF_MYSTRUCTDATA != 0)
    {
        try
        {
            Clipboard clipbrd;
            clipbrd.Empty();
            clipbrd.SetData(CF_MYSTRUCTDATA, data);
            return true;
        }
        catch (const std::runtime_error&)    
        {
        }
    }
    return false;
}

bool GetData(sData &data) const
{
    if (CF_MYSTRUCTDATA != 0)
    {
        try
        {
            Clipboard clipbrd;
            clipbrd.GetData(CF_MYSTRUCTDATA, data);
            return true;
        }
        catch (const std::runtime_error&)
        {
        }
    }
    return false;
}