分类: C/C++
2008-03-31 14:45:19
后两个参数基本上没有什么利用价值,我想到Hook IDataObject的GetData函数,可是在Ole Drop客户端编程时,通常当我调用COleDataObject的相关成员函数时拖放已经差不多完成,鼠标已经在我的程序窗口上了。
而我现在的想法是在拖放操作刚离开Word的文档窗口,还没有到达外部程序窗口时就让它失效,这样Hook IDataObject的虚函数肯定不行,我只有再研究一下最后一个没有研究过的参数pDropSource,它是一个IDropSource类型指针,我发现它有一个虚函数QueryContinueDrag查看了一下MSDN发现它似乎就是我要找的。
我的理解是这个函数是让Ole拖放的服务端在调用DoDragDrop启动Ole拖放操作后,有机会取消拖放操作而设的一个CallBack,于是我写了一段代码Hook住DoDragDrop并从DoDragDrop中进一步Hook住IDropSource的QueryContinueDrag虚函数,我发现它会全程跟踪整个拖放操作,只要这个CallBack一返回DRAGDROP_S_CANCEL整个拖放操作就会被取消,这样我只要知道当前鼠标下的窗口是否是文档窗口就可以了,一旦离开了文档窗口我就让这个CallBack返回DRAGDROP_S_CANCEL取消整个拖放操作。
这样做就可以不影响文档窗口内部的拖放操作,又可以阻止将文档窗口内部的东西拖放到其它程序中,基本上不会让客户感到不方便,这很有意思!不是吗?
那么从鼠标位置得到窗口句柄可能吗?答案是肯定的! GetCursorPos函数可以返回一个POINT变量,它指示当前的鼠标位置,而WindowFromPoint则可以返回某一个POINT位置下的窗口句柄。写到这里我想差不多已经说完了我的思路,不知道你是否看得明白。
总结一下,用ATL向导生成一个COM框架,增加一个ATL简单对象,在这个对象上实现_IDTExtensibility2接口,在_IDTExtensibility2的OnConnection中Hook住DoDragDrop API,在Word调用DoDragDrop时记录下当前的文档窗口句柄,并Hook住第二个参数pDropSource的QueryContinueDrag虚函数,在QueryContinueDrag里跟踪当前鼠下的窗口是否还是文档窗口(比较句柄是否等于DoDragDrop时记录下的文档窗口句柄),如果不是则返回DRAGDROP_S_CANCE取消拖放操作,并弹出一个警告信息的MessageBox,否则执行原有的操作(让拖放操作正常进行)。
最后,别忘了注册你的Word插件(用Regsvr32。exe),详细的键值和代码细节见源程序吧!
2005年10月15日夜
参考资料: