拖放功能的实现

类别:VC语言 点击:0 评论:0 推荐:

    最近编写了一个需要用到拖放功能的软件,之前本人对其还不神了解,找了网上的一些资料但多说的不是很直接。在这里说说我的心得。
    以下所说的拖放功能是急于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 不要也可以反正是执行空函数,不信就跟进去看看吧
    好了这样一个拖放的过程就完成了,在读的地方设置个断点看看数据是不是传送过来了啊,有的话就恭喜恭喜了,没有就从新检查一遍吧

本文地址:http://com.8s8s.com/it/it512.htm