2020年(目标管理)实现Drop目标对象

上传人:精****库 文档编号:136065031 上传时间:2020-06-23 格式:DOC 页数:9 大小:72.65KB
返回 下载 相关 举报
2020年(目标管理)实现Drop目标对象_第1页
第1页 / 共9页
2020年(目标管理)实现Drop目标对象_第2页
第2页 / 共9页
2020年(目标管理)实现Drop目标对象_第3页
第3页 / 共9页
2020年(目标管理)实现Drop目标对象_第4页
第4页 / 共9页
2020年(目标管理)实现Drop目标对象_第5页
第5页 / 共9页
点击查看更多>>
资源描述

《2020年(目标管理)实现Drop目标对象》由会员分享,可在线阅读,更多相关《2020年(目标管理)实现Drop目标对象(9页珍藏版)》请在金锄头文库上搜索。

1、第六部分:实现Drop目标对象(OLE drag&drop 之旅) 欢迎你到OLE拖放操作的第六章!这里将着重于一个实现了drop-target的小程序,这就意味着我们的程序能够接收拖到它上面的对象(文件、图片、文本)了。我们实现一个IDropTarget的COM接口允许OLE程序拖动数据到我们的程序上;这里仅仅是一个简单的EDIT控件,所以他将CF_TEXT数据作为目标。成为一个“Drop Target”为了时窗口可以接收拖放操作的数据,窗口必须注册为drop目标;有一个OLE的API调用RegisterDragDrop来完成这个事情,函数的原型是:WINOLEAPI RegisterDra

2、gDrop (HWND hwnd, IDropTarget * pDropTarget);第一个参数是窗口的HANDLE,这个窗口是拖动的目标窗口;第二个参数是一个指向IDropTarget COM对象的指针,COM/OLE运行时将在拖放操作的过程中调用这个方法。同样有一个OLE API调用来将window从拖放操作中删除:WINOLEAPI RevokeDragDrop(HWND hwnd);我们所要做的就是在窗口创建的时候调用RegisterDragDrop,在窗口销毁的时候调用RevokeDragDrop。在我们调用RegisterDragDrop之前,我们需要构造一个COM对象来支持I

3、DropTarget接口。IDropTarget接口IDropTarget接口相对比较简单,有四个函数需要实现,当然,也要实现IUnknown接口,不过我们前面已经介绍了。IDropTarget 方法描述DragEnter判断是否可以接受一个拖操作,以及接受之后的效果DragOver提供通过DoDragDrop函数执行的目标反馈DragLeave导致一个drop目标挂起它的返回行为Drop数据放进目标窗口这些函数都由COM/OLE运行时在一个对象被拖到我们注册窗口的时候来调用。就象上表显示的一样,每个函数都有不同的任务,我们需要做的就是实现这些函数。实现IDropTarget以我的经验,IDr

4、opTarget接口非常难以写为不涉及特定程序的代码,例如:写成可以在所有程序都使用的通用IDropTarget COM对象是很难的。这是因为IDropTarget要求在一个对象拖过你的目标窗口时显示图形效果,且也只有特定程序代码才可以访问这些数据对象内容。在我们的拖放接口之外,IDropTarget是最容易被集成到你窗口类的对象。例如:假定你已经用C+类实现了一个自定义的窗口,为这个窗口添加一个多drop目标支持的最好方法就是从IDropTarget直接继承,而不需要单独定义一个CDropTarget类;这意味着你的drop-target代码能够访问所有你的窗口状态。然而,我们这里提供完整的

5、CDropTarget类:class CDropTarget : public IDropTargetpublic: / IUnknown implementation HRESULT _stdcall QueryInterface (REFIID iid, void * ppvObject); ULONG _stdcall AddRef (void);ULONG _stdcall Release (void); / IDropTarget implementation HRESULT _stdcall DragEnter(IDataObject * pDataObject, DWORD gr

6、fKeyState, POINTL pt, DWORD * pdwEffect); HRESULT _stdcall DragOver(DWORD grfKeyState, POINTL pt, DWORD * pdwEffect); HRESULT _stdcall DragLeave(void); HRESULT _stdcall Drop(IDataObject * pDataObject, DWORD grfKeyState, POINTL pt, DWORD * pdwEffect); / Constructor CDropTarget(HWND hwnd); CDropTarget

7、();private: / internal helper function DWORD DropEffect (DWORD grfKeyState, POINTL pt, DWORD dwAllowed); bool QueryDataObject(IDataObject *pDataObject); / Private member variables long m_lRefCount; HWND m_hWnd; bool m_fAllowDrop; / Other internal window members;除引用记数器外,我们需要存储另外两个变量:m_hWnd变量是drop-tar

8、get窗口的HANDLE,这个在提供可见效果的时候需要;m_fAllowDrop用来指示被拖动的数据对象是否包含我们需要的有用数据。因此我们没有连续查询数据对象,这是一个最优的办法。IDropTarget:DragEnter方法让我们首先看一下IDropTarget函数,因为这是在一个对象被拖过我们窗口时最先被COM调用的函数:HRESULT DragEnter ( IDataObject * pDataObject,/指向源数据对象的接口指针 DWORD grfKeyState, / 当前键盘修饰符的状态 POINTL pt, / 当前鼠标的坐标 DWORD * pdwEffect / 指向

9、拖放操作的效果指针 );仔细看一下上面函数的原型,因为这对于理解每个参数怎么样使用很重要:l IDataObject-第一个参数是拖放操作的源对象通过COM传递来的数据对象指针。IDataObject是拖放操作带来数据的传输媒体,我们在DragEnter的时候查看数据对象来看是否有我们想要的任何数据。l grfKeyState-保留键盘修饰符的状态,例如:Control、Alt、和Shift以及鼠标按键的状态。是有一到多个MK_CONTROL、MK_SHIFT、MK_ALT、MK_BUTTON、MK_LBUTTON等组成的简单DWORD变量l pt-一个POINTL结构体,包含了鼠标进入我们窗

10、口的坐标;在许多程序中,这个参数用来检查鼠标是否放置在允许的drop区域上,或者用来简单的放置某些插入光标来指示drop数据放在那里。l pdwEffect-一个DWORD的指针,指出drop源允许的drop效果。这个值和DoDragDrop的dwOKEffect值相同。我们的DragEnter实现需要做几个通常的工作,另外画一个图形的反馈:1. 检查提供的数据对象,然后判断它是否包含任何有用的数据2. 检查存储在grfKeyState的键盘状态,并且计算应该是什么样的drop效果,例如:如果Control键按下,drop效果应该是复制,如果Shift被按下,drop效果应该是移动。3. 验证

11、这些效果是否与drop源的效果相兼容4. 存储最终的drop效果到pdwEffect的DWORD指针。不要如此复杂吧!DragEnter的目的就是简单的对拖放操作说“yes还是NO”,指定采用什么drop效果以便于OLE更新鼠标光标。HRESULT _stdcall CDropTarget:DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) / does the dataobject contain data we want? m_fAllowDrop = QueryDataOb

12、ject (grfKeyState, pdwEffect, pDataObject); if(m_fAllowDrop) / get the dropeffect based on keyboard state *pdwEffect = DropEffect (grfKeyState, pt, *pdwEffect); SetFocus (m_hWnd); PositionCursor (m_hWnd, pt); else *pdwEffect = DROPEFFECT_NONE; return S_OK;除了设置光标下的窗口和设置EDIT位置外,DragEnter的功能已经由两个内部协助函数

13、代理而简化了:bool CDropTarget:QueryDataObject(IDataObject *pDataObject) FORMATETC fmtetc = CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL ; / does the data object support CF_TEXT using a HGLOBAL? return pDataObject-QueryGetData(&fmtetc) = S_OK ? true : false;QueryDataObject是一个私有函数,纯粹用来检查提供的数据,然后决定它是否包含对我

14、们的drop目标有用的数据。在我们的例子中,我们仅仅接受CF_TEXT数据存储为HGLOBAL,因此这是我们请求的类型。一个私有成员变量m_fAllowDrop用来记住这个决定。DWORD CDropTarget:DropEffect (DWORD grfKeyState, POINTL pt, DWORD dwAllowed)DWORD dwEffect = 0;/ 1. 检查pt来看是否允许drop操作在某个位置/ 2. 计算出基于grfKeyState的drop效果if(grfKeyState & MK_CONTROL)dwEffect = dwAllowed & DROPEFFECT_COPY;else if(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

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 商业/管理/HR > 企业文档

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号