利用MFC实现对象拖放



本文讨论了对象拖放技术,并研究了如何利用MFC实现该技术;利用MFC实现对象拖放,编程比较容易,代码可读性好。 

1.对象拖放概念 
  对象拖放是指对某一指定的对象,利用鼠标拖动的方法,在不同应用的窗口之间、同一应用的不同窗口之间或同一应用的同一窗口内进行移动、复制(粘贴)等操作的技术。   

  对象拖放是在操作系统的帮助下完成的。 要开始一次拖动, 首先需要指定或生成被拖动的对象,然后指定整个拖放操作过程所使用的数据格式,并按指定的数据格式提供数据,最后启动对象拖放操作;当对象在某一窗口内落下时,拖放过程结束,接收拖放对象的窗口按指定的数据格式提取有关数据,并根据提取的数据生成对象。  

2.MFC中用于对象拖放的类 
MFC(Microsoft Foundation ClassLibrary)为实现对象拖放提供了如下三个类。为便于后边的讨论我们先来熟悉一下这些类。  

2.1.COleDataSource。用于启动一次拖放操作,并向系统提供拖放对象的数据。类中的成员函数有如下三种:  

a.设定提供数据的方式和使用的数据格式。提供数据的方式有两种,一种是即时方式,另一种是延迟方式;即时方式需要在拖动开始之前提供数据;延迟方式不需要立即提供数据,当系统请求有关数据时,由OnRenderData()等虚函数提供所需的数据。可以用CacheGlobalData()等函数指定使用即时方式提供数据,也可以用DelayRenderData ()等函数指定使用延时方式提供数据。   

b.响应请求,提供数据。应当重载OnRenderFileData()或其他相应的虚函数,以提供有关数据(后边将详细讨论)。  

c.实施拖放操作。调用函数DoDragDrop(),开始实施拖放操作。


2.2.OleDataTarget。用于准备接收拖放对象的目标窗口;一个窗口要想能够接收拖放对象,必须包含一个COleDataTarget对象,并注册该对象。类中主要成员函数: 

a.注册。函数Register()注册该对象,以便使窗口能够接收拖放对象。


     b.响应拖放过程中的动作(虚成员函数) 当鼠标首次进入窗口时系统将调用OnDragEnter(),当鼠标移出窗口时系统将调用OnDragLeave(), 当鼠标在窗口内移动,系统将重复调用调用OnDragOver(),当对象在窗口内落下调用OnDrop()  

2.3.OleDataObject.用于接收拖放对象,类中主要成员函数有两种:  

a.确定可以使用的数据格式。IsDataAvailable()等函数确定指定数据格式是否可用;   

b.获取数据。GetData()GetFileData()等函数用于按指定数据格式获得数据。   

3.利用MFC实现对象拖放 

  要实现一次对象拖放,需要做三方面的工作:对象所在的窗口准备拖放对象并启拖动操作,接受对象的窗口响应有关拖放消息并接受落下的对象,以及拖放完成时的后期处理。以下分别予以介绍。   

3.1. 拖动操作的启动。拖放操作一般是从单击鼠标左键开始。在消息WM_LBUTTONDOWN的响应 

  函数OnLButtonDown(...)中,首先要判定是否选定了某一对象,如果未选定或选定多个,则不能进 行拖放操作;如果选定了一个对象,则可以进行拖放操作。要启动一次拖放操作,需要先准备一个COleDataSource对象。注意到类COleClientItem和类COleServerItem都是从类COleDataSource上派生的,如果选定的是COleClientItem对象或者是COleServerItem对象,则可以直接使用;否则,需要生成一个COleDataSource对象,值得注意的是:需要象上文中所说的,应该指定使用的数据格式,并按指定格式提供对象的有关数据。 
 
  下面给出准备数据源的例子: 

class myDataSource: public COleDataSource 

public: 
COLORREF color; 
CString str; 
protected: 
virtual BOOL OnRenderFileData(LPFORMATETC,CFile*); 
//...... 
}; 

BOOL myDataSource::OnRenderFileData(LPFORMATETC lpFormatEtc,CFile* pFile) 

if(lpFormatEtc->cfFormat==CF_TEXT) 

pFile.Write("Test DragDrop",13); //Magic String 
pFile.Write(amp;color,sizeof(COLORREF)); 
int len= str.GetLength(); 
pFile.Write(len,sizeof(int)); 
pFile.Write(str,len); 
return TRUE; 
} 

COleDataSource::OnRenderFileData(lpFormatEtc,pFile); 
return FALSE; 
} 

  有了以上数据源之后,就可以在消息WM_LBUTTON的响应函数OnLButtonDown()中,按如下方式,指定使用的数据格式:   

myDataSource* pItemDragDrop=new myDataSource; 
pItemDragDrop->str="This string will dragdrop to another place"; 
pItemDragDrop->DelayRenderFileData(CF_TEXT,NULL);   

  指定好使用的数据格式之后,调用此对象的成员函数DoDragDrop(...),启动对象拖放操作。需要注意的是,函数DoDragDrop(...)并不立即返回,而是要等到鼠标按钮弹起之后。   

3.2. 拖放对象的接收。缺省情况下,一般的窗口是不能接收拖放对象的;要使窗口可以接收拖放对象,需要在窗口类定义中加入成员对象COleDropTarget,并在生成窗口时调用函数COleDataTarget::Register()。例如: 

Class myView : public CScrollView 

private: 
COleDropTarget oleTarget; 
protected: 
virtual int OnCreate(LPCREATESTRUCT); 
//...... 
} 

int myView::OnCreate(LPCREATESTRUCT lpCreateStruct) 

//...... 
dropTarget.Register(this); 
return 0; 


  为实现拖放对象的接收,还应重载CViewCOleDropTarget的虚函数:COnDragMove()OnDragEnter()OnDrop()等。函数OnDragEnter()OnDragMove()应根据鼠标在窗口中的位置,返回以下数值: 

DROPEFFECT_MOVE---表明可以把对象复制到现在的窗口、现在的位置; 
DROPEFFECT_COPY---表明可以把对象从原来的窗口、原来的位置移到现在的窗口、现在的位置; 
DROPEFFECT_NONE---表明不能在该窗口的该位置放下。 
  下例只允许移动对象,而不允许复制对象
DROPEFFECT myView::OnDragEnter(......) 

return DROPEFFECT_MOVE; 
} 

DROPEFFECT myView::OnDragOver(......) 

return DROPEFFECT_MOVE; 
} 

  函数OnDrop()应处理拖动对象放下后的工作。该函数的参数pDataObjec指向一个COleDataObject对象,利用指针,可以获取有关数据。该函数的一般实现是: 

a.检查对象的数据格式利用函数COleDataObject::IsDataAvailable() 
b.按指定的格式获取数据:利用COleDataObject::GetFileData()等函数; 
c.建立对象(可能与原对象相同,也可能不建立对象仅使用对象中的数据):利用以上步骤 

  得到的数据建立对象。例如: 

char magic_string[13]; 
COLORREF color; 
CString str; 
int len; 
myDataSource* pMyData; 

if(IsDataAvailable(CF_TEXT)) 

CFile file=GetFileData(CF_TEXT);  

file.Read(magic_string,13); 
if(strncmp(magic_string,"Test DragDrop",13)==0) 

file.Read(amp;color,sizeof(COLORREF)); 
file.Read(len,sizeof(int)); 
file.Read(str,len);  

CClientDC dc(this); 
dc.SetTextColor(color); 
dc.SetBkMode(TRANSPARENT); 
dc.TextOut(100,50,str,len);  

pMyData=new myDataSource; 
pMyData->color=color; 
pMyData->str=str; 

} 

  对于COleClientItemCOleServerItem对象,可以按以下方法很容易地重建对象: 

COleClient* pItem=GetDocument()->CreateNewItem() 
pItem->CreateFrom(pDataObject);   

3.3. 拖放操作的结束函数DoDragDrop()返回时,拖放过程结束。函数DoDragDrop()的返回值,表明了对象的拖放结果。 

DROPEFFECT_MOVE:对象被放到他处,需删除原对象 
DROPEFFECT_COPY:对象被复制到他处,不删除原对象 
DROPEFFECT_NONE:未能实现拖放,无需删除原对象  

  例如: 

int DragEffect=pItemTracking->DoDragDrop(......); 
switch(DragEffect) 

case DROPEFFECT_MOVE: 
delete pItemTracking; 
GetDocument()->UpdateAllItems(NULL); 
GetDocument()->UpdateAllViews(NULL); 
break; 
case DROPEFFECT_COPY: 
case DROPEFFECT_NONE: 
default: 
break; 
}

 

本文讨论了对象拖放技术,并研究了如何利用MFC实现该技术;利用MFC实现对象拖放,编程比较容易,代码可读性好。 

  
1.对象拖放概念 
  对象拖放是指对某一指定的对象,利用鼠标拖动的方法,在不同应用的窗口之间、同一应用的不同窗口之间或同一应用的同一窗口内进行移动、复制(粘贴)等操作的技术。   

  对象拖放是在操作系统的帮助下完成的。 要开始一次拖动, 首先需要指定或生成被拖动的对象,然后指定整个拖放操作过程所使用的数据格式,并按指定的数据格式提供数据,最后启动对象拖放操作;当对象在某一窗口内落下时,拖放过程结束,接收拖放对象的窗口按指定的数据格式提取有关数据,并根据提取的数据生成对象。 
 

  
2.MFC中用于对象拖放的类 
  MFC(Microsoft Foundation ClassLibrary)为实现对象拖放提供了如下三个类。为便于后边的讨论我们先来熟悉一下这些类。  

  2.1.COleDataSource。用于启动一次拖放操作,并向系统提供拖放对象的数据。类中的成员函数有如下三种:  
 

  a.设定提供数据的方式和使用的数据格式。提供数据的方式有两种,一种是即时方式,另一种是延迟方式;即时方式需要在拖动开始之前提供数据;延迟方式不需要立即提供数据,当系统请求有关数据时,由OnRenderData()等虚函数提供所需的数据。可以用CacheGlobalData()等函数指定使用即时方式提供数据,也可以用DelayRenderData ()等函数指定使用延时方式提供数据。  
 

  b.响应请求,提供数据。应当重载OnRenderFileData()或其他相应的虚函数,以提供有关数据(后边将详细讨论)。 
 

  c.实施拖放操作。调用函数DoDragDrop(),开始实施拖放操作。


  2.2.OleDataTarget。用于准备接收拖放对象的目标窗口;一个窗口要想能够接收拖放对象,必须包含一个COleDataTarget对象,并注册该对象。类中主要成员函数: 

  a.注册。函数Register()注册该对象,以便使窗口能够接收拖放对象。


      b.响应拖放过程中的动作(虚成员函数) 当鼠标首次进入窗口时系统将调用OnDragEnter(),当鼠标移出窗口时系统将调用OnDragLeave(), 当鼠标在窗口内移动,系统将重复调用调用OnDragOver(),当对象在窗口内落下调用OnDrop()   

  2.3.OleDataObject.用于接收拖放对象,类中主要成员函数有两种:  
 

  a.确定可以使用的数据格式。IsDataAvailable()等函数确定指定数据格式是否可用;  
 

  b.获取数据。GetData()GetFileData()等函数用于按指定数据格式获得数据。  
 

  3.利用MFC实现对象拖放   

  要实现一次对象拖放,需要做三方面的工作:对象所在的窗口准备拖放对象并启拖动操作,接受对象的窗口响应有关拖放消息并接受落下的对象,以及拖放完成时的后期处理。以下分别予以介绍。  
 

  3.1. 拖动操作的启动。拖放操作一般是从单击鼠标左键开始。在消息WM_LBUTTONDOWN的响应
 

  函数OnLButtonDown(...)中,首先要判定是否选定了某一对象,如果未选定或选定多个,则不能进 行拖放操作;如果选定了一个对象,则可以进行拖放操作。要启动一次拖放操作,需要先准备一个COleDataSource对象。注意到类COleClientItem和类COleServerItem都是从类COleDataSource上派生的,如果选定的是COleClientItem对象或者是COleServerItem对象,则可以直接使用;否则,需要生成一个COleDataSource对象,值得注意的是:需要象上文中所说的,应该指定使用的数据格式,并按指定格式提供对象的有关数据。
 
  
 
  下面给出准备数据源的例子: 

  
class myDataSource: public COleDataSource 
  

  
public: 
  
COLORREF color; 
  
CString str; 
  
protected: 
  
virtual BOOL OnRenderFileData(LPFORMATETC,CFile*); 
  
//...... 
  };  
 

  
BOOL myDataSource::OnRenderFileData(LPFORMATETC lpFormatEtc,CFile* pFile) 
  

  
if(lpFormatEtc->cfFormat==CF_TEXT) 
  

  
pFile.Write("Test DragDrop",13); //Magic String 
  
pFile.Write(amp;color,sizeof(COLORREF)); 
  
int len= str.GetLength(); 
  
pFile.Write(len,sizeof(int)); 
  
pFile.Write(str,len); 
  
return TRUE; 
  }  
 

  
COleDataSource::OnRenderFileData(lpFormatEtc,pFile); 
  
return FALSE; 
  }  
 

  有了以上数据源之后,就可以在消息WM_LBUTTON的响应函数OnLButtonDown()中,按如下方式,指定使用的数据格式:  
 

  
myDataSource* pItemDragDrop=new myDataSource; 
  
pItemDragDrop->str="This string will dragdrop to another place"; 
  pItemDragDrop->DelayRenderFileData(CF_TEXT,NULL);  
 

  指定好使用的数据格式之后,调用此对象的成员函数DoDragDrop(...),启动对象拖放操作。需要注意的是,函数DoDragDrop(...)并不立即返回,而是要等到鼠标按钮弹起之后。  
 

  3.2. 拖放对象的接收。缺省情况下,一般的窗口是不能接收拖放对象的;要使窗口可以接收拖放对象,需要在窗口类定义中加入成员对象COleDropTarget,并在生成窗口时调用函数COleDataTarget::Register()。例如:
 

  
Class myView : public CScrollView 
  

  
private: 
  
COleDropTarget oleTarget; 
  
protected: 
  
virtual int OnCreate(LPCREATESTRUCT); 
  
//...... 
  }  
 

  
int myView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  

  
//...... 
  
dropTarget.Register(this); 
  
return 0; 
  


  为实现拖放对象的接收,还应重载CViewCOleDropTarget的虚函数:COnDragMove()OnDragEnter()OnDrop()等。函数OnDragEnter()OnDragMove()应根据鼠标在窗口中的位置,返回以下数值:
 

  DROPEFFECT_MOVE---表明可以把对象复制到现在的窗口、现在的位置;
 
  DROPEFFECT_COPY---表明可以把对象从原来的窗口、原来的位置移到现在的窗口、现在的位置;
 
  DROPEFFECT_NONE---表明不能在该窗口的该位置放下。 

  下例只允许移动对象,而不允许复制对象
  
DROPEFFECT myView::OnDragEnter(......) 
  

  
return DROPEFFECT_MOVE; 
  }  
 

  
DROPEFFECT myView::OnDragOver(......) 
  

  
return DROPEFFECT_MOVE; 
  }  
 

  函数OnDrop()应处理拖动对象放下后的工作。该函数的参数pDataObjec指向一个COleDataObject对象,利用指针,可以获取有关数据。该函数的一般实现是:
 

  a.检查对象的数据格式利用函数COleDataObject::IsDataAvailable()
 
  b.按指定的格式获取数据:利用COleDataObject::GetFileData()等函数;
 
  c.建立对象(可能与原对象相同,也可能不建立对象仅使用对象中的数据):利用以上步骤
 

  得到的数据建立对象。例如:
 

  
char magic_string[13]; 
  
COLORREF color; 
  
CString str; 
  
int len; 
  myDataSource* pMyData;  
 

  
if(IsDataAvailable(CF_TEXT)) 
  

  CFile file=GetFileData(CF_TEXT);   
 

  
file.Read(magic_string,13); 
  
if(strncmp(magic_string,"Test DragDrop",13)==0) 
  

  
file.Read(amp;color,sizeof(COLORREF)); 
  
file.Read(len,sizeof(int)); 
  file.Read(str,len);   
 

  
CClientDC dc(this); 
  dc.SetTextColor(color); 
  
dc.SetBkMode(TRANSPARENT); 
  dc.TextOut(100,50,str,len);   
 

  
pMyData=new myDataSource; 
  
pMyData->color=color; 
  
pMyData->str=str; 
  

  }  
 

  对于COleClientItemCOleServerItem对象,可以按以下方法很容易地重建对象:
 

  COleClient* pItem=GetDocument()->CreateNewItem()
 
  pItem->CreateFrom(pDataObject);  
 

  3.3. 拖放操作的结束函数DoDragDrop()返回时,拖放过程结束。函数DoDragDrop()的返回值,表明了对象的拖放结果。
 

  DROPEFFECT_MOVE:对象被放到他处,需删除原对象
 
  DROPEFFECT_COPY:对象被复制到他处,不删除原对象
 
  DROPEFFECT_NONE:未能实现拖放,无需删除原对象 
 

  例如:
 

  
int DragEffect=pItemTracking->DoDragDrop(......); 
  
switch(DragEffect) 
  

  
case DROPEFFECT_MOVE: 
  
delete pItemTracking; 
  
GetDocument()->UpdateAllItems(NULL); 
  
GetDocument()->UpdateAllViews(NULL); 
  
break; 
  
case DROPEFFECT_COPY: 
  
case DROPEFFECT_NONE: 
  
default: 
  
break; 
  }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值