我的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);
}
答案 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;
}