数据对象剪贴板传输,COleDataSource和COleDataObject用法

//以下是一个用COleDataSource和ColeDataObject通过剪贴板传输一个对象Bitmap的方法,,数据格式为CF_DIB(系统已定义的)//若使用自定义的数据格式,请看下数据格式结构体CLIPFORMAT,然后还得使用RUINT RegisterClipboardFormat(LPCTSTR lpszFormat),具体用法,请查资料吧//m_dib是CEx25aDoc一个CDib对象公共成员,

 
void CEx25aView::OnEditCopy()
{
	// TODO: Add your command handler code here
	COleDataSource* pSource = SaveDib();//此处我们得到了一个new分配出来的COleDataSource对象,如何删除看下面
	if(pSource){
		pSource->SetClipboard(); //此处COleDataSource对象中的数据被系统传输到剪贴板,,然后系统自动把GloableAlloc分配的内存释放,并且把new分配的CO//leDateSource释放
	}
}


 
COleDataSource* CEx25aView::SaveDib(void)
{
	CDib& dib = GetDocument()->m_dib;
	if(dib.GetSizeImage() > 0){
		COleDataSource* pSource = new COleDataSource(); //此处使用堆分配
		int nHeaderSize = dib.GetSizeHeader();//此处为计算出Bitmap文件的头大小
		int nImageSize = dib.GetSizeImage();//此处为Bitmap文件的数据部分大小
		HGLOBAL hHeader = ::GlobalAlloc(GMEM_MOVEABLE,nHeaderSize + nImageSize);//分配大小,MSDN上说此函数中GMEM_MOVEABLE参数表示,得到的HGLOBAL内.存句柄得使用GlobalLock得到分配空间的指针,用完后,还得使用GlobalUnlock解除
		LPVOID pHeader = ::GlobalLock(hHeader);
		ASSERT(pHeader != NULL);
		LPVOID pImage = (LPBYTE)pHeader+nHeaderSize;
		memcpy(pHeader,dib.m_lpBMIH,nHeaderSize);//
		memcpy(pImage,dib.m_lpImage,nImageSize);//拷贝数据,Receiver is supposed to free the global memory
 		::GlobalUnlock(hHeader); //使用GlobalUnlock解除
		pSource->CacheGlobalData(CF_DIB,hHeader); //将分配的全局内存数据插入到数据对象缓冲区中
		return pSource;
	}
	return NULL;
}
void CEx25aView::OnEditPaste()
{
	// TODO: Add your command handler code here
	CEx25aDoc* pDoc = GetDocument();
	COleDataObject dataObject;  //接收剪贴板信息时,使用的是局部变量COleDataObject
	VERIFY( dataObject.AttachClipboard());
	DoPasteDib(&dataObject);
	CClientDC dc(this);
	pDoc->m_dib.UsePalette(&dc);
	pDoc->SetModifiedFlag();
	pDoc->UpdateAllViews(NULL);
}
BOOL CEx25aView::DoPasteDib(COleDataObject* pDataObject)
{
	//update command user interface should keep us out of here if not CF_DIB
	if(!pDataObject->IsDataAvailable(CF_DIB)){
		TRACE("CF_DIB format is unavailable \n");
		return FALSE;
	}
	CEx25aDoc* pDoc = GetDocument();
	//seems to be MOVEABLE memory ,so we must use GlobalLock!
	//(hDib != lpDib) GetGlobalData copies the memory ,so we can hang onto it until we delete the CDib
	HGLOBAL hDib = pDataObject->GetGlobalData(CF_DIB); //此处使用GetGlobalData从剪贴板获得数据时,会申请内存从剪贴板中拷贝一份!
//若用BOOL COleDataObject::GetData(CLIPFORMAT cfFormat,LPSTGMEDIUM lpStgMedium,LPFORMATETC lpFormatEtc)的话,会将数据传输到lpStgMedium指向的结构体
	ASSERT(hDib != NULL);
	LPVOID lpDib = ::GlobalLock(hDib);
	ASSERT(lpDib != NULL);
	pDoc->m_dib.AttachMemory(lpDib,true,hDib);
	pDoc->SetModifiedFlag();
	pDoc->UpdateAllViews(NULL);
	return TRUE;
}
没用这个发过代码,弄的好悲剧




  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
查看位图的信息(右键查看): 1.文件头 2.信息头 3.RGB掩码(如果有的话) 显示出来的形式如下: BITMAPFILEHEADER* = 0x02800048 BITMAPFILEHEADER .bfType = 0x4D42 .bfSize = 552158 .bfReserved1 = 0 .bfReserved2 = 0 .bfOffBits = 66 BITMAPINFOHEADER .biSize = 40 .biWidth = 353 .biHeight = 391 .biPlanes = 1 .biBitCount = 32 .biCompression = BI_BITFIELDS .biSizeImage = 552092 .biXPelsPerMeter = 0 .biYPelsPerMeter = 0 .biClrUsed = 0 .biClrImportant = 0 Red Mask = 00FF0000 Green Mask = 0000FF00 Blue Mask = 000000FF 说明: 1.第一行为内存中malloc出来的地址,由于是虚拟内存,不看也罢 2.该程序不止可以查看BITMAPINFOHEADER类型的位图, 其余三种类型也可查看,分别为: BITMAPCOREHEADER、BITMAPV4HEADER、BITMAPV5HEADER 3.最后三行的RGB Mask是颜色掩码,对于BITMAPINFOHEADER类型来说,不一定有。 4.右键功能是查看信息,左键是左右镜像操作,由于是底层数据直接每行左右互换, 而对于1、4位深的这两种位图,底层数据操作涉及位操作,而我还在写这个位图类, 故暂不支持,只支持8位以上的水平镜像操作。 5.支持剪切板操作,并且是以CF_DIB或CF_DIBV5呼叫GetClipboardData函数的, 复制时,也是以该参数呼叫SetClipboardData函数的。 你可以复制其他地方的图片过来,以查看图片属性。 6.程序中运行中保存在内存中的图片是BITMAPFILEHEADER*指针,不是HBITMAP, 呼叫的显示函数是SetDIBitsToDevice函数。 7.鼠标在图片上移动是,右边填充鼠标点的颜色,标题栏也有相关显示。 下边显示鼠标点附近11*11像素范围的放大图像,正中间用十字叉线画出。 取色是直接在底层取数据解析。 8.改程序在《windows程序设计》上的一个例子改编而来,并且正在完善该位图类中, 以加入更多丰富的底层操作功能。 改试验程序主要供想研究位图结构的人查看用。 9.windows搞出了4种位图种类,真作孽~~ 另,16、24、32位深的位图也可以有颜色表的,该程序已考虑在内。 10.下面四种压缩格式暂不支持: BI_RLE8、BI_RLE4、BI_JPEG、BI_PNG 11.随带的附件中,有几张不同格式的位图,你可以试验打开查看。 有问题联系:hastings1986@163.com
1. 在对话框资源中添加一个Listbox控件,并设置好ID和属性。 2. 在类视图中添加成员变量,将Listbox控件变量类型设置为CListBox,如下所示: ``` CListBox m_lstData; ``` 3. 在OnInitDialog函数中,进行Listbox控件的初始化,如下所示: ``` m_lstData.SubclassDlgItem(IDC_LIST_DATA, this); ``` 4. 实现拖拽操作,可以在Listbox控件的OnLButtonDown和OnMouseMove函数中实现,如下所示: ``` void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point) { // 获取选中的项 int nIndex = m_lstData.ItemFromPoint(point); // 如果没有选中项,则返回 if (nIndex == LB_ERR) return; // 设置拖拽数据 COleDataSource* pDataSource = new COleDataSource(); HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, 1024); char* pData = (char*)GlobalLock(hMem); m_lstData.GetText(nIndex, pData); GlobalUnlock(hMem); pDataSource->CacheGlobalData(CF_TEXT, hMem); // 开始拖拽操作 DROPEFFECT dropEffect = pDataSource->DoDragDrop(DROPEFFECT_COPY); // 释放资源 pDataSource->Empty(); delete pDataSource; CDialogEx::OnLButtonDown(nFlags, point); } void CMyDlg::OnMouseMove(UINT nFlags, CPoint point) { // 如果鼠标左键没有按下,则返回 if (!(nFlags & MK_LBUTTON)) return; // 设置拖拽效果 COleDropSource* pDropSource = new COleDropSource(); DROPEFFECT dropEffect = pDropSource->StartDrag(); // 释放资源 delete pDropSource; CDialogEx::OnMouseMove(nFlags, point); } ``` 5. 实现拖拽放置操作,可以在Listbox控件的OnDrop函数中实现,如下所示: ``` DROPEFFECT CMyDlg::OnDragEnter(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point) { // 如果数据对象不包含文本,则返回 if (!pDataObject->IsDataAvailable(CF_TEXT)) return DROPEFFECT_NONE; return DROPEFFECT_COPY; } BOOL CMyDlg::OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point) { // 如果数据对象不包含文本,则返回 if (!pDataObject->IsDataAvailable(CF_TEXT)) return FALSE; // 获取文本数据 HGLOBAL hMem = pDataObject->GetGlobalData(CF_TEXT); char* pData = (char*)GlobalLock(hMem); CString strData(pData); GlobalUnlock(hMem); // 添加到Listbox控件中 m_lstData.AddString(strData); return TRUE; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值