第1页共9页编号:时间:2021年x月x日书山有路勤为径,学海无涯苦作舟页码:第1页共9页第六部分:实现Drop目标对象(OLEdrag&drop之旅)欢迎你到OLE拖放操作的第六章!这里将着重于一个实现了drop-target的小程序,这就意味着我们的程序能够接收拖到它上面的对象(文件、图片、文本)了。我们实现一个IDropTarget的COM接口允许OLE程序拖动数据到我们的程序上;这里仅仅是一个简单的EDIT控件,所以他将CF_TEXT数据作为目标。成为一个“DropTarget”为了时窗口可以接收拖放操作的数据,窗口必须注册为drop目标;有一个OLE的API调用RegisterDragDrop来完成这个事情,函数的原型是:WINOLEAPIRegisterDragDrop(HWNDhwnd,IDropTarget*pDropTarget);第一个参数是窗口的HANDLE,这个窗口是拖动的目标窗口;第二个参数是一个指向IDropTargetCOM对象的指针,COM/OLE运行时将在拖放操作的过程中调用这个方法。同样有一个OLEAPI调用来将window从拖放操作中删除:WINOLEAPIRevokeDragDrop(HWNDhwnd);我们所要做的就是在窗口创建的时候调用RegisterDragDrop,在窗口销毁的时候调用RevokeDragDrop。在我们调用RegisterDragDrop之前,我们需要构造一个COM对象来支持IDropTarget接口。IDropTarget接口IDropTarget接口相对比较简单,有四个函数需要实现,当然,也要实现IUnknown接口,不过我们前面已经介绍了。IDropTarget方法描述DragEnter判断是否可以接受一个拖操作,以及接受之后的效果DragOver提供通过DoDragDrop函数执行的目标反馈DragLeave导致一个drop目标挂起它的返回行为Drop数据放进目标窗口第2页共9页第1页共9页编号:时间:2021年x月x日书山有路勤为径,学海无涯苦作舟页码:第2页共9页这些函数都由COM/OLE运行时在一个对象被拖到我们注册窗口的时候来调用。就象上表显示的一样,每个函数都有不同的任务,我们需要做的就是实现这些函数。实现IDropTarget以我的经验,IDropTarget接口非常难以写为不涉及特定程序的代码,例如:写成可以在所有程序都使用的通用IDropTargetCOM对象是很难的。这是因为IDropTarget要求在一个对象拖过你的目标窗口时显示图形效果,且也只有特定程序代码才可以访问这些数据对象内容。在我们的拖放接口之外,IDropTarget是最容易被集成到你窗口类的对象。例如:假定你已经用C++类实现了一个自定义的窗口,为这个窗口添加一个多drop目标支持的最好方法就是从IDropTarget直接继承,而不需要单独定义一个CDropTarget类;这意味着你的drop-target代码能够访问所有你的窗口状态。然而,我们这里提供完整的CDropTarget类:classCDropTarget:publicIDropTarget{public://IUnknownimplementationHRESULT__stdcallQueryInterface(REFIIDiid,void**ppvObject);ULONG__stdcallAddRef(void);ULONG__stdcallRelease(void);//IDropTargetimplementationHRESULT__stdcallDragEnter(IDataObject*pDataObject,DWORDgrfKeyState,POINTLpt,DWORD*pdwEffect);HRESULT__stdcallDragOver(DWORDgrfKeyState,POINTLpt,DWORD*pdwEffect);HRESULT__stdcallDragLeave(void);HRESULT__stdcallDrop(IDataObject*pDataObject,DWORDgrfKeyState,POINTLpt,DWORD*pdwEffect);//Constructor第3页共9页第2页共9页编号:时间:2021年x月x日书山有路勤为径,学海无涯苦作舟页码:第3页共9页CDropTarget(HWNDhwnd);~CDropTarget();private://internalhelperfunctionDWORDDropEffect(DWORDgrfKeyState,POINTLpt,DWORDdwAllowed);boolQueryDataObject(IDataObject*pDataObject);//Privatemembervariableslongm_lRefCount;HWNDm_hWnd;boolm_fAllowDrop;//Otherinternalwindowmembers};除引用记数器外,我们需要存储另外两个变量:m_hWnd变量是drop-target窗口的HANDLE,这个在提供可见效果的时候需要;m_fAllowDrop用来指示被拖动的数据对象是否包含我们需要的有用数据。因此我们没有连续查询数据对象,这是一个最优的办法。IDropTarget::DragEnter方法让我们首先看一下IDropTarget函数,因为这是在一个对象被拖过我们窗口时最先被COM调用的函数:HRESULTDragEnter(IDataObject*pDataObject,//指向源数据对象...