版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
欢迎阅读本文档,希望本文档能对您有所帮助!欢迎阅读本文档,希望本文档能对您有所帮助!感谢阅读本文档,希望本文档能对您有所帮助!感谢阅读本文档,希望本文档能对您有所帮助!欢迎阅读本文档,希望本文档能对您有所帮助!感谢阅读本文档,希望本文档能对您有所帮助!第六部分:实现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数据放进目标窗口这些函数都由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);//ConstructorCDropTarget(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,//指向源数据对象的接口指针DWORDgrfKeyState,//当前键盘修饰符的状态POINTLpt,//当前鼠标的坐标DWORD*pdwEffect//指向拖放操作的效果指针);仔细看一下上面函数的原型,因为这对于理解每个参数怎么样使用很重要:
IDataObject-第一个参数是拖放操作的源对象通过COM传递来的数据对象指针。IDataObject是拖放操作带来数据的传输媒体,我们在DragEnter的时候查看数据对象来看是否有我们想要的任何数据。
grfKeyState-保留键盘修饰符的状态,例如:Control、Alt、和Shift以及鼠标按键的状态。是有一到多个MK_CONTROL、MK_SHIFT、MK_ALT、MK_BUTTON、MK_LBUTTON等组成的简单DWORD变量
pt-一个POINTL结构体,包含了鼠标进入我们窗口的坐标;在许多程序中,这个参数用来检查鼠标是否放置在允许的drop区域上,或者用来简单的放置某些插入光标来指示drop数据放在那里。
pdwEffect-一个DWORD的指针,指出drop源允许的drop效果。这个值和DoDragDrop的dwOKEffect值相同。我们的DragEnter实现需要做几个通常的工作,另外画一个图形的反馈:1.
检查提供的数据对象,然后判断它是否包含任何有用的数据2.
检查存储在grfKeyState的键盘状态,并且计算应该是什么样的drop效果,例如:如果Control键按下,drop效果应该是复制,如果Shift被按下,drop效果应该是移动。3.
验证这些效果是否与drop源的效果相兼容4.
存储最终的drop效果到pdwEffect的DWORD指针。不要如此复杂吧!DragEnter的目的就是简单的对拖放操作说“yes还是NO”,指定采用什么drop效果以便于OLE更新鼠标光标。HRESULT__stdcallCDropTarget::DragEnter(IDataObject*pDataObject,DWORDgrfKeyState,POINTLpt,DWORD*pdwEffect){//doesthedataobjectcontaindatawewant?m_fAllowDrop=QueryDataObject(grfKeyState,pdwEffect,pDataObject);if(m_fAllowDrop){//getthedropeffectbasedonkeyboardstate*pdwEffect=DropEffect(grfKeyState,pt,*pdwEffect);SetFocus(m_hWnd);PositionCursor(m_hWnd,pt);}else{*pdwEffect=DROPEFFECT_NONE;}returnS_OK;}除了设置光标下的窗口和设置EDIT位置外,DragEnter的功能已经由两个内部协助函数代理而简化了:boolCDropTarget::QueryDataObject(IDataObject*pDataObject){FORMATETCfmtetc={CF_TEXT,0,DVASPECT_CONTENT,-1,TYMED_HGLOBAL};//doesthedataobjectsupportCF_TEXTusingaHGLOBAL?returnpDataObject->QueryGetData(&fmtetc)==S_OK?true:false;}QueryDataObject是一个私有函数,纯粹用来检查提供的数据,然后决定它是否包含对我们的drop目标有用的数据。在我们的例子中,我们仅仅接受CF_TEXT数据存储为HGLOBAL,因此这是我们请求的类型。一个私有成员变量m_fAllowDrop用来记住这个决定。DWORDCDropTarget::DropEffect(DWORDgrfKeyState,POINTLpt,DWORDdwAllowed){ DWORDdwEffect=0; //1.检查pt来看是否允许drop操作在某个位置 //2.计算出基于grfKeyState的drop效果 if(grfKeyState&MK_CONTROL) { dwEffect=dwAllowed&DROPEFFECT_COPY; } elseif(grfKeyState&MK_SHIFT) { dwEffect=dwAllowed&DROPEFFECT_MOVE; } //3.非键盘修饰符指定(或drop效果不允许),因此基于drop源的效果 if(dwEffect==0) { if(dwAllowed&DROPEFFECT_COPY)dwEffect=DROPEFFECT_COPY; if(dwAllowed&DROPEFFECT_MOVE)dwEffect=DROPEFFECT_MOVE; } returndwEffect;}DropEffect协助函数用来计算基于键盘状态的drop效果,并且这个效果是达到源允许的。首先grfKeyState变量用来检查看是否使用了Control或Shift键;这些键的标准的OLE行为是Control应该是复制数据,shift应该是移动数据。如果两个都按下,数据应该是连接(例如:源应该建立一个到目标的快捷方式),但我们不支持这个功能。主要的事情是使用位与操作符来对dwEffect赋drop效果值的时候:dwEffect=dwAllowed&DROPEFFECT_COPY;这个分配的结构很简单-dwEffect将拥有DROPEFFECT_COPY,但只有在dwAllowed变量中仅仅包含这个值的时候起作用;这种逻辑用法防止我们强制执行一个源不允许的drop效果。下面是看一下在没有键盘修饰符的时候怎么做,例如:Control和Shift没有使用。在这种情况我,我们检查拖放的源对象允许的drop效果,以及选择使用哪个效果;在我们的实现中,我们是移动数据而不是复制。IDropTarget::DragOver方法这个函数在拖放操作的整个生命周期中被多次调用,因此,高效的写这个函数很重要;DragOver在键盘修饰符改变(shift/control等)或当鼠标移动的时候被调用。告诉OLE采用什么样基于键盘状态和鼠标位置的drop效果是这个函数的责任:HRESULT__stdcallCDropTarget::DragOver(DWORDgrfKeyState,POINTLpt,DWORD*pdwEffect){if(m_fAllowDrop){*pdwEffect=DropEffect(grfKeyState,pt,*pdwEffect);PositionCursor(m_hWnd,pt);}else{*pdwEffect=DROPEFFECT_NONE;}returnS_OK;}DragOver写的很简单,逻辑上与DragEnter相同,我们使用前面计算过的m_fAllowDrop和DropEffect协助函数来通过pdwEffect指针返回drop效果。IDropTarget::DragLeave函数这个函数在鼠标光标移到drop目标窗口外面的时候调用,或者按下Escape键来取消拖放操作时。它的原型如下:HRESULT__stdcallCDropTarget::DragLeave(void){returnS_OK;}这是这个函数的基本写法;这个函数存在的唯一原因是便于程序在鼠标移到窗口外面的时候使用图形返回效果来得到一个机会清理。例如:想象下面的场景,无论什么东西都拖过目标对象,DragEnter函数用来改变窗口边界的颜色;在这种情况下,DragLeave函数用来恢复窗口边界的颜色。IDropTarget::Drop函数Drop函数的原型与DragEnter函数相同:HRESULT__stdcallCDropTarget::Drop(IDataObject*pDataObject,DWORDgrfKeyState,POINTLpt,DWORD*pdwEffect){PositionCursor(m_hWnd,pt);if(m_fAllowDrop){DropData(m_hWnd,pDataObject);*pdwEffect=DropEffect(grfKeyState,pt,*pdwEffect);}else{*pdwEffect=DROPEFFECT_NONE;}returnS_OK;}在OLE判断拖放操作到头的时候调用该函数,我们得到一个在DragEnter同样的IDataObject的接口指针,我们可以从中得到数据并粘贴到我们的编辑窗口中。DropData协助函数用来访问数据对象内部的CF_TEXT数据,并插入到edit控件中;这个程序是是纯理论的,我们已经知道怎么样访问一个数据对象了,这里不在不厌其烦的介绍,你可以看源代码。postedon2006-03-0608:51笨笨阅读(606)评论(2)
编辑
收藏\o"功能强大的网络收藏夹,一秒钟操作就可以轻松实现保存带来的价值、分享带来的快乐"收藏至365Key所属分类:OLEDrag&Drop
评论:\o"permalink:re:第六部分:实现Drop目标对象(OLEdrag&drop之旅)"#
re:第六部分:实现Drop目标对象(OLEdrag&drop之旅)2006-05-24
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025-2026学年巴西音乐说课稿教学
- 2025-2026学年大班数学说课稿认识单双数
- 2025-2026学年保护牙齿教育活动说课稿
- 2025-2026学年初三语文下册说课说课稿
- 2025-2026学年初中地理试卷说课稿
- 2026下半年下半年初中化学教资面试酸碱专项题库
- 2025-2026学年八年级地理下册说课稿人教版
- 2026下半年下半年高中化学教资面试计算解析
- 《形体与减肥》课件
- 2025-2026学年动作律动舞蹈说课稿
- 2026-2030中国锰矿行业供需形势分析及前景需求量预测研究报告
- 沉浸式数字艺术展策展、运营及衍生品开发指南
- 《安全生产责任保险事故预防服务规范 第3部分:危险化学品》AQ 9010.3-2026
- AI大模型安全评估及防护技术应用指南2026
- 安徽省合肥市肥东县2025-2026学年上学期七年级期末数学试卷(试卷+解析)
- 2026年及未来5年中国野猪行业市场深度研究及投资战略咨询报告
- 2025年东莞初中音乐考编笔试及答案
- 坦克课件教学课件
- 絮凝技术应用
- 2026年湖南商务职业技术学院单招职业技能考试题库附答案解析
- DB3304∕T 087-2022 稻田退水零直排工程建设规范
评论
0/150
提交评论