Internet Explorer 编程简述(十一)实现完美的Inplace Drag & Drop——“超级拖放”

测试C++代码与WebBrowser HTML的互动 testWebBrowserDlg.h testWebBrowserDlg.cpp test.html 阅读详情
关键字:超级拖放,GetDropTarget,ondragover,IHTMLDataTransfer
 
1、概述
许多多窗口浏览器都提供了一种被称为“超级拖放”(或“超级拖拽”、“随心拖放”等等,不一而足)的功能。作为对IE拖拽行为对扩展,“超级拖放”实现了一些非常实用的功能:
  • 拖放网页链接:通常是在新窗口中打开
  • 拖放选中的文字:保存文字、作为关键字通过搜索引擎搜索网络、作为Url打开等
  • 拖放图片:通常是保存图片到指定文件夹
  • 当然,还有很关键的一点:拖动对象时鼠标指针反馈不同的拖拽效果
在《 Internet Explorer 编程简述(十)响应来自HTML Element的事件通知——几个好用的类 》中曾提到,尽管许多浏览器都提供了超级拖放的功能,但与IE的缺省实现相比,除了具备鼠标指针拖拽效果外,还没有哪个浏览器的实现能够实现:
  • 文字在页面内与输入框之间的交互拖放(这一点最为重要)
  • 来自外部的文字与网页输入框之间的交互拖放
  • 拖拽时滚动页面(这一点是被忽略了)
 
本文的目的,一是介绍实现超级拖放的两种方法,二是说明如何实现“完美”的拖放——即扩展IE拖拽行为的同时,保留IE默认的拖拽行为。三是给出一个最为直接和简洁的实现,至于拖放不同的对象以实现不同的功能,不在本文讨论的范围,略去。
 
 
2、标准的实现方法
标准方法即通过IDocHostUIHandler的GetDropTarget成员函数来实现,在MSDN这样说到:
IDocHostUIHandler::GetDropTarget Method——Called by MSHTML when it is used as a drop target. This method enables the host to supply an alternative IDropTarget interface.
即在适当的时候,MSHTML引擎会调用IDocHostUIHandler的GetDropTarget方法,为应用程序提供一个机会来替换MSHTML缺省的DropTarget实现。我们就可以通过这个自定义的DropTarget实现来完成上述的“超级拖放”功能。方法示例如下,其中略去的部分可参考MFC中CHtmlControlSite和CHtmlView的源代码:
 
STDMETHODIMP CHtmlControlSite::XDocHostUIHandler::GetDropTarget(
LPDROPTARGET pDropTarget, LPDROPTARGET* ppDropTarget)
{
METHOD_PROLOGUE_EX_(CHtmlControlSite, DocHostUIHandler)
*ppDropTarget = g_pDropTarget;//将自定义的实现告知MSHTML引擎
return S_OK;
}
 
其中g_pDropTarget指向某个全局的IDropTarget接口的实现,我们假定为CIEDropTarget,CIEDropTarget实现了IDropTarget的几个成员函数DragEnter、DragOver、DragLeave和Drop。在DragEnter中可以决定是否接受一个Drop以及如果接受这个Drop的话该提供怎样的鼠标拖拽反馈,在持续触发的DragOver中同样可以设定鼠标拖拽反馈,从而实现在拖放不同的对象(文字、链接、图像等)时提供不同的拖拽视觉效果,实现相当简单,此处不再赘述。
但上面的实现存在一些问题。首先是选中的文字在页面内与输入框之间交互的拖放没有了。这是自然的,既然我们用自定义的DropTarget替换掉了IE的缺省实现,那这种交互的拖放理应由我们自己实现。难处并非在于不能实现,而是在于实现起来比较麻烦——光是得到鼠标下的HTML Element就够我们烦了;当输入框中有文字的时候,光标还应该随着鼠标的移动而移动——所以这个费力还不一定讨好的功能似乎没有哪个浏览器去做。其次,作为输入框文字拖放的衍生物,拖拽滚动没有了。当鼠标向某个方向拖拽时,网页应该随着将不可见的部分滚动出来,比如某个输入框,让我们有机会将文字拖拽过去。这个Feature的实现并不困难,不过一来是被忽略了(注意到拖拽滚动的人并不多),二来主要Feature都没有实现,这个滚动也意义不大了。
 
3、打入MSHTML内部
既然从GetDropTarget提供外部实现难以得到与输入框的交互式拖放,那就换个角度来考虑问题,让我们打入MSHTML的内部。
着手点是IHTMLDocumentX接口——操纵IE的DOM的法宝。我们注意到IHTMLDocument2有个ondragstart事件,进而想到应该也有诸如ondragenter、ondragover、ondrop之类的事件(事实上也是有的),如果响应这些事件,处理同输入框的交互式拖放应该就能够解决。因为这些拖放在MSHTML的缺省DropTarget实现中发生,因而当鼠标拖拽到某个输入框上时,肯定会触发一个ondragover事件,而在IHTMLEventObj的辅助下我们能轻松得到相关的HTML Element,其它的操作就容易进行了。再细心一点,我们还发现IHTMLEventObj2接口有个dataTransfer属性——可以得到一个IHTMLDataTransfer的指针,而IHTMLDataTransfer接口正是浏览器内部用于数据交换的重要手段之一(看看它的属性就知道会很有用了):
IHTMLDataTransfer Members
clearData——Removes one or more data formats from the clipboard through dataTransfer or clipboardData object.
dropEffect——Sets or retrieves the type of drag-and-drop operation and the type of cursor to display.
effectAllowed——Sets or retrieves, on the source element, which data transfer operations are allowed for the object.
getData——Retrieves the data in the specified format from the clipboard through the dataTransfer or clipboardData objects.
setData——Assigns data in a specified format to the dataTransfer or clipboardData object.
 
更进一步,从IHTMLDataTransfer接口还可以访问到IDataObject接口,在进行Ole拖放时,数据就是通过IDataObject接口来传递的。具体用法稍后讨论。
 
4、打入MSHTML内部——思路
提供鼠标反馈效果与实现GetDropTarget的方法类似,有了IHTMLDataTransfer接口,便可在ondragstart及ondragover事件触发时通过dropEffect属性设置拖拽的效果(可根据需要自行设定,不设置的话使用默认的效果)。再者,“拖”和“放”都在MSHTML的缺省实现中发生,我们从IHTMLEventObj的SrcElement即可得知鼠标所位置的HTML Element是否是输入框。
 
5、打入MSHTML内部——实现
要接收到ondragstart之类的事件,可以采用《 Internet Explorer 编程简述(十)响应来自HTML Element的事件通知——几个好用的类 》中提到的CHtmlObj类和CHtmlElements类,并在适当的地方连接到Document,示例代码如下所示:
 
HRESULT CHtmlDocument2::OnInvoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags,
DISPPARAMS * pdispparams, VARIANT * pvarResult,EXCEPINFO * pexcepinfo,
C# 继承.Net中提供的WebBrowser 2.0控件以实现IE超级拖放 看到傲游中提供的超级拖放很是方便,但是IE中却没有提供,但是现在IE 8 用着很好,于是就琢磨着自能否让IE 也支持此功能呢,Google一下很多都是VC++的资料,而且没有完整的代码,但是有一篇的文章给出了完整的思路,这里很感谢此作者,原文链接:http://blog.csdn.net/drong/archive/2007/03/05/1520698.aspx通过该作者的思路对控件进行了改写 阅读详情

相关推荐

html5 datatransfer,HTML5讲解之dataTransfer对象

[导读] HTML5拖拽的数据传输  虽然通过dragstart、dragdragend事件实现了原生拖拽。但是这仅仅是拖拽,在IE6和IE7中还是有些拖拽问题,并且也没有实现数据的交换。为了实现数据的交换,IE5引入了dataTransfer对象。HTML5拖拽的数据传输虽然通过dragstart、dragdragend事件实现了原生拖拽。但是这仅仅是拖拽,在IE6和IE7中还是有些拖拽问题...

weixin_35890512的博客 773

Drag And Drop 进阶

Drag And Drop 进阶 上一篇文章我们介绍了基本的Drag And Drop 编程和其运行机制。 为了我们的初衷,自动往打开的explorer 管理窗口发送我们的文件,我们应该想到,如果采用静态的枚举当前所有窗口然后进行独立的操作的话,新生成的资源管理器窗口无法被操作。因此,我们应该想一种方法,即使是新生成的窗口也会运行我们的代码。 答案是:窗口钩子。 窗口钩子简介 SetWi

商少 946

HTML5实战与剖析之原生拖拽(三dataTransfer对象)

虽然通过dragstart、dragdragend事件实现了原生拖拽。但是这仅仅是拖拽,在IE6和IE7中还是有些拖拽问题,并且也没有实现数据的交换。为了实现数据的交换,IE5引入了dataTransfer对象。dataTransfer对象是事件对象的一个属性,用于从被拖拽元素相放置目标传递字符串格式的数据。因为它是事件对象的属性,所以只能在拖放事件的事件处理程序中访问dataT

梦龙小站 1万+

IE编程转载

2个比较好的ie编程文章:牛人啊http://blog.csdn.net/CathyEagle/archive/2006/03/11/621961.aspxhttp://blog.csdn.net/CathyEagle/archive/2006/04/25/677425.aspx 顺便记录下Internet Explorer 编程简述(十)响应来自HTML Element的事件通知

dick_china的专栏 2097

win7及以上系统C++实现Hook explorer文件级监控复制、剪切和删除操作

最近项目组需要实现一个对windows用户文件操作进行监控的功能,(也就是使用explorer资源管理器的操作),于是乎我就想到了使用Hook的方法进行拦截,查找一番资料后发现XP调用的是最简单的CopyFileEx, MoveFileWithProgressW, ReplaceFileW之类的API,所以XP是最好解决的,但是到了Vista及以后的系统中,微软采用了一种新的方法——com组件里的...

BruceAYG的博客 7510

html5的元素拖拽

html5 元素拖拽

讨厌走开啦 7818

兼容浏览器(IE,火狐,谷歌)js实现拖拽效果从<http://www.jb51.net/article/38034.htm>转载

var isDrag = false; function isIE(){ if(navigator.userAgent.indexOf("MSIE")>0){ return true; }else{ return false; } } function addListener(element,e,fn){ if(isIE()){ element.a

周文超的专栏 1061

delphi 控件 TEmbeddedWB 实现超级拖拽 (super Drag&amp;Drop OR inline Drag&amp;Drop)

//处理超级拖拽function TForm1.DropEvent(const dataObj: IDataObject;  grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HRESULT;var  aFmtEtc : TFORMATETC;  aStgMed : TSTGMEDIUM;  pData : PChar;begin 

soweb的专栏 1643

Internet Explorer 编程简述(五)调用IE隐藏的命令(中文版)

关键字:Add To Favorite, Import/Export Wizard, Shell DocObject View, Internet Explorer_Server1、概述除了“整理收藏夹”和“添加到收藏夹”对话框外,还有其它一些对话框是我们希望直接通过WebBrowser调用的,比如“导入/导出”对话框,用一般的方法很难调用。IShellUIHelper尽管提供了ImportE

eagleboost's blog 1万+

Internet Explorer 编程简述(九)在自己的浏览器中嵌入Google工具条

 关键字:Google Toolbar, Explorer Bars, ToolBands, IObjectWithSite, IDeskBand 1、概述  Internet Explorer强大而方便的可编程能力和可扩展能力为其抢占浏览器市场可谓是立下了汗马功劳。可编程主要体现两方面: 实现浏览功能的部分被包装成一个控件——WebBrowser Control,开

eagleboost's blog 1万+

老文章——TWebBrowser编程简述

引 言  这篇文章最先发表于2000年07月25日,最后一次修改是在2001年02月07日。这里再次贴出的目的,一是作为前一阶段的完结,所以文章中的错误都不作修改;二是希望作为一个新的起点。我准备整理一下至今所积累的浏览器编程的知识,比较完整地写出来,与网友共勉。TWebBrowser编程简述摘要:Delphi 3开始有了TWebBrowser构件,不过那时是以ActiveX控件的形式

eagleboost's blog 1万+

利用浏览器实现程序界面与实现的分离

关键字 WebBrowser,IDocHostUIHandler,GetExternal1 引言在用Delphi、Visual Basic等可视化快速开发工具编写Windows应用程序时,常会遇到这样几个问题:1) 希望程序界面美观。在Delphi中,开发人员通常使用各种控件来实现界面的风格化,但缺点是造成应用程序体积较大,且在升级时常会被控件版本与Delphi版本不兼容带来的问题所困扰。2)

eagleboost's blog 1万+

FAQ:如何访问WebBrowser的滚动条

问========================================我使用webbrowser控件,但是想用自己的滚动条,但不知如何得到webbrowser中滚动条的长度,怎么办?谢谢!!2004-10-24答========================================    抱歉拖了很久才回复你的问题。    WebBrowser的滚动条不是一般的Windows

eagleboost's blog 1万+
上一篇: 响应AutoComplete下拉列表的选择事件
下一篇: IE & Delphi再次复活
eagleboost
博客等级 码龄27年 67粉丝 56原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值