//用于自定义数组/结构体数组的剪切板应用类
template <class MYDATA> class COwnerArrayDataClipboard
{
//用于剪切板数据结构体
typedef struct tagMYSTRUCTARRAY_t
{
int iCount; //记录数据个数
MYDATA data[1]; //数据
}MYSTRUCTARRAY, *LPMYSTRUCTARRAY;
HWND hClipboardHwnd; //剪切板窗口句柄
UINT uFormat; //剪切板粘贴格式
//Trace Error
#define TraceErr(e) \
do{ \
dwErr=GetLastError();\
TRACE( _T(#e) _T(" Error Code:%ld\n"), dwErr);\
ASSERT(FALSE);\
}while(0);
public:
COwnerArrayDataClipboard()
{
//以桌面窗口做剪切板窗口句柄
hClipboardHwnd = GetDesktopWindow();
//注册剪切板格式
CString szFormat;
szFormat.Format(_T("ClipBoard_%d"), sizeof(MYDATA));
uFormat = RegisterClipboardFormat( szFormat );
if(uFormat == 0)
{
DWORD dwErr = GetLastError();
TRACE( _T("RegisterClipboardFormat failed : %ld\n"), dwErr);
ASSERT(FALSE);
}
}
//链表粘贴到剪切板
//iCont 指示 DataArray个数
//DataArray源数据
BOOL PasteToClipboard(const int iBuffCount, const MYDATA DataArray[])
{
DWORD dwErr = ERROR_SUCCESS;
HGLOBAL hMem = NULL;
BOOL bClipOpened = FALSE;
do
{
//打开剪切板
bClipOpened = OpenClipboard(hClipboardHwnd);
if(!bClipOpened)
{
TraceErr("OpenClipboard");
break;
}
//清空剪切板
if(!EmptyClipboard())
{
TraceErr("EmptyClipboard");
break;
}
//分配所需内存
DWORD dwSize = sizeof(MYSTRUCTARRAY) + (iBuffCount-1) * sizeof(MYDATA); //计算长度
hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, dwSize); //分配内存
if(hMem == NULL)
{
TraceErr("GlobalAlloc");
break;
}
//锁定内存
LPMYSTRUCTARRAY pArray = (LPMYSTRUCTARRAY)GlobalLock(hMem);
if(pArray == NULL)
{
TraceErr("GlobalLock");
break;
}
//拷贝数据至内存
{
pArray->iCount = iBuffCount; //拷贝结构体个数
for(int i=0; i<iBuffCount; i++)
{
pArray->data[i] = DataArray[i]; //拷贝结构体数据
}
}
//解锁内存
if(!GlobalUnlock(hMem) && GetLastError() != ERROR_SUCCESS)
{
TraceErr("GlobalUnlock");
break;
}
if(SetClipboardData(uFormat, hMem) == NULL)
{
TraceErr("SetClipboardData");
break;
}
} while (0);
//出错释放内存
if(dwErr && hMem)
{
GlobalFree(hMem);
hMem = NULL;
}
//关闭剪切板
if(bClipOpened)
CloseClipboard();
return dwErr == ERROR_SUCCESS;
}
//从剪切板读取数据
//用于存放返回 DataArray数据缓冲区
//iBuffCount 输入时指示缓冲区大小
//函数返回值:
//当DataArray==NULL 或 iBuffCount==0时 返回 剪切板中可用的数据个数
//当否则返回实际读取的个数
int CopyFromClipboard(MYDATA DataArray[], const int iBuffCount)
{
int iCount = 0;
DWORD dwErr = ERROR_SUCCESS;
BOOL bClipOpened = FALSE;
do
{
//打开剪切板
bClipOpened = OpenClipboard(hClipboardHwnd);
if(!bClipOpened)
{
TraceErr("OpenClipboard");
break;
}
if(!IsClipboardFormatAvailable(uFormat))//检查格式有效
{
TraceErr("IsClipboardFormatAvailable");
break;
}
HGLOBAL hMem = GetClipboardData(uFormat);//读取数据句柄
if(hMem == NULL)
{
TraceErr("GetClipboardData");
break;
}
//锁定内存
LPMYSTRUCTARRAY pArray = (LPMYSTRUCTARRAY)GlobalLock(hMem);
if(pArray == NULL)
{
TraceErr("GlobalLock");
break;
}
//拷贝数据至内存
if(DataArray == NULL || iBuffCount <= 0)
{
iCount = pArray->iCount;
}
else
{
iCount = min(iBuffCount, pArray->iCount);
for(int i=0; i<iCount; i++)
{
DataArray[i] = pArray->data[i];
}
}
//解锁内存
if(!GlobalUnlock(hMem) && GetLastError() != ERROR_SUCCESS)
{
TraceErr("GlobalUnlock");
break;
}
} while (0);
//关闭剪切板
if(bClipOpened)
CloseClipboard();
return iCount;
}
};
//测试
//测试结构体
typedef struct tagMYSTRUCT_t
{
int a, b, c;
tagMYSTRUCT_t()
{
a = b = c = 0;
}
tagMYSTRUCT_t(int a1, int b1, int c1)
{
a = a1; b = b1; c = c1;
}
tagMYSTRUCT_t( tagMYSTRUCT_t & other)
{
memcpy(this, &other, sizeof(*this));
}
}MYSTRUCT, *LPMYSTRUCT;
void TestOwnerArrayDataClipboard()
{
//准备源数据
const int iSrcCount = 5;
MYSTRUCT myStruct1[iSrcCount];
for(int i=0; i<iSrcCount; i++)
{
myStruct1[0].a = i+1;
}
COwnerArrayDataClipboard < MYSTRUCT > clipboard;
//粘贴到剪切板
clipboard.PasteToClipboard(iSrcCount, myStruct1);
//获取长度
int iDstCount = clipboard.CopyFromClipboard(NULL, 0);
ASSERT(iDstCount == iSrcCount);
//读取全部数据
MYSTRUCT *myStruct2 = new MYSTRUCT[iDstCount];
clipboard.CopyFromClipboard(myStruct2, iDstCount);
for(int j=0; j<iDstCount; j++)
{
if(memcmp(&myStruct1[j], &myStruct2[j], sizeof(MYSTRUCT)) != 0)
{
ASSERT(FALSE);
}
}
//清理
delete []myStruct2;
}