最近编写了一个需要用到拖放功能的软件,之前本人对其还不神了解,找了网上的一些资料但多说的不是很直接。在这里说说我的心得。 以下所说的拖放功能是急于OLE的所以在程序的初始化中确认有如下的语句: if (!AfxOleInit()) { return FALSE; } 这个原因费了我很多时间啊 拖放有一个源和一个目的,所以实现的时候需要有两个主要的类:源类COleDataSource、目的类COleDropTarget。 源的实现必须从COleDataSource类派生而来,由于源和目的必须有信息的传送。所以COleDataSource提供了几种信息传送方式,这里先介绍一种OnRenderFileData(LPFORMATETC lpFormatEtc,CFile* pFile),这个函数是从COleDataSource继承下来并实现的。以下是类的源码我的一个例子传送一个文本到目的控件
class CMyDataSource : public COleDataSource { protected:
// Attributes public: // Operations public: public: CString m_strGifFullPath; virtual ~CMyDataSource(); CMyDataSource();
// Generated message map functions protected: virtual BOOL OnRenderFileData(LPFORMATETC,CFile*); }; BOOL CMyDataSource::OnRenderFileData(LPFORMATETC lpFormatEtc,CFile* pFile) { if(lpFormatEtc->cfFormat==CF_TEXT) { CArchive ar(pFile, CArchive::store); ar.WriteString(m_strGifFullPath); ar << (BYTE)'\0'; //注意试图不要关闭ar和pFile否则目的控件就不能接受到信息 return TRUE; }
COleDataSource::OnRenderFileData(lpFormatEtc,pFile); return FALSE;
} 启动拖放功能,我是从ListCtrl中拖出来的所以在OnBegindragFileList事件中写代码的 , 当然也可以在其他事件中启动,如左键按下。代码如下 CMyDataSource ItemDragDrop; ItemDragDrop.DelayRenderFileData(CF_TEXT,NULL);//执行OnRenderFileData来获取数据 ItemDragDrop.m_strGifFullPath ="要传送的内容"; int iRes = ItemDragDrop.DoDragDrop();//直到左键弹起才返回 switch(iRes) {//完成拖放后的处理 case DROPEFFECT_MOVE: break; case DROPEFFECT_COPY: break; case DROPEFFECT_NONE: default: break; } 目的接收功能实现考COleDropTarget类完成的,添加一个成员到你的视图类中如COleDropTarget m_oleDropTarget;,并在视图类的OncCreate函数中注册该成员m_oleDropTarget.Register(this);工作完成一般,下面就是具体的接收代码了。 在视图类中有下面几个虚函数需要重写(很多文章中说消息,搞不懂), OnDrop最后放下时调用 OnDragOver在视图上时调用 OnDragEnter鼠标刚进入视图时调用 OnDragLeave鼠标离开视图时调用 下面代码主要修改OnDrop和OnDragOver函数 全部使用默认的代码是不是OnDrop怎么都不调用啊 ,呵呵我也搞了很久才懂啊 因为默认代码OnDragOver返回值是DROPEFFECT_NONE所以OnDrop就不发生了,因此必须重写函数返并返回非DROPEFFECT_NONE值,简单一点就 return DROPEFFECT_COPY;好了。这时就断点调试停下了吧。没停下我也不懂了。 OndDrop函数的代码如下 if(pDataObject->IsDataAvailable(CF_TEXT)) { CFile *pFile = pDataObject->GetFileData(CF_TEXT); //这个时候就会去调用源的OnRenderFileData函数了 CArchive ar(pFile, CArchive::load); CString str; ar.ReadString(str); ar.Close();// delete pFile;//记得关闭和析构哦,否则就内存泄漏咯 } return TRUE;//默认的return 不要也可以反正是执行空函数,不信就跟进去看看吧 好了这样一个拖放的过程就完成了,在读的地方设置个断点看看数据是不是传送过来了啊,有的话就恭喜恭喜了,没有就从新检查一遍吧 
|