WebBrowser控件拖拽的实现

 WebBrowser 作为群众喜闻乐见的插件, 一直以好用难写而臭名昭著.

 

其海量的接口忙的众多死程序员乐不思蜀.

 

前些天正好需要在WebBrowser中实现文件的拖拽, 遇到一些问题, 后来解决了, 希望和大家分享分享.

 

俺是菜鸟,大家包涵.

 

环境:  纯SDK ( 没有用MFC, 因为mfc太方便了,所以显得臃肿,有些问题反而复杂化了 ,所以用SDK模式讲解)

 

大家知道 WebBrowser 有一个有名的接口叫: IDocHostUIHandler

 

关于这个接口的详细教学可以参看下面的链接:

 

http://www.vckbase.com/document/viewdoc/?id=1486

 

唯一不足之处就是基于MFC, 不过这个接口很容易转换成SDK模式的,很简单.

 

在IDocHostUIHandler 中有一个函数, GetDropTarget( IDropTarget *pDropTarget,IDropTarget **ppDropTarget)

传说重载这个函数, 然后返回, 可以替换默认的拖拽处理( 默认的拖拽处理是下载这个被拖拽的文件)

在上面的接口教学的文章中, 作者似乎用mfc HTML 模块很容易就实现了这个功能.

可是,很快有人就反映了问题:

http://topic.csdn.net/u/20071130/10/c8fb0fe8-776a-42d3-b340-a5fce0568cda.html

该提问者直到最后,几乎解决问题, 但还是差了一点. 可惜已经结贴,无法再回答他的问题.

 

实际上对于拖拽的实现, 原理还是COM类的, 在mfc中提供了一个类 , COleDropTarget. 这个类被许多类,比如 CView 所继承.

通过这个类"实现"了拖拽. 我打上引号,是因为事实不竟然.

该类的实现文件在 X : /Program Files/Microsoft Visual Studio 9.0/VC/atlmfc/src/mfc/oledrop2.cpp

下面是一个使用他的教程: (你可以看,也可以直接掠过,因为作用和我们说的关系不大)

http://www.vckbase.com/document/viewdoc/?id=258

(我讨厌MFC的原因是,明明一个简单的事情, 他为了实现一点点的简洁,却使用了非常繁琐的技术,让我头大.)

 

根据那位同学的思路,其实可以有两种实现.

方法一:

使用 RegisterDragDrop(...)   告诉系统,定义某个窗口为拖拽窗口.

函数原型:

 参数 hwnd 是要接受拖拽窗口的句柄.

 参数 pDropTarget 是处理拖拽的IDropTarget的指针.

 注意 pDropTarget 是要求用户自己实现的.

  1. WINOLEAPI RegisterDragDrop( 
  2.   HWND hwnd,  //Handle to a window that can accept drops
  3.   IDropTarget * pDropTarget
  4.               //Pointer to object that is to be target of drop
  5. );

你还需要在自己实现的IDocHostUIHandler中的GetDropTarget中简单返回S_OK,告诉WebBrowser 你自定义拖拽.
  1. HRESULT 
  2. YourDocHostUIHandler::GetDropTarget( IDropTarget *pDropTarget, IDropTarget **ppDropTarget)
  3. {
  4.     //使用用户定义的拖拽
  5.     return S_OK;
  6. }

注意RegisterDragDrop参数hwnd是接受拖拽窗口的句柄,  必须是窗口自己,不能是子窗口,不能是父窗口.

许多人应当知道,也许不知道, MFC HTML 中给出的 m_hWnd 其实不是接受拖拽窗口的窗口,而是他的框架窗口.

请使用Sky++查看WebBrowser窗口的组成.

你会发现 m_hWnd 是最外层的窗口,  而实际窗口是一个有名的,类名如雷贯耳的:  Internet Explorer_Server 的窗口, 正是这个窗口

才是真正应该接受拖拽的窗口.

前面那位同学尽管使用了 RegisterDragDrop ,但是仍然不能接受拖拽,问题正是他没有注册 Internet Explorer_Server 这个窗口为拖拽, 相反,注册了他的祖父辈窗口, 这样当然无法实现.

当然在MFC中问题被掩盖了, 但是有时候还是会冒出这种问题,当你没有"按照上帝的旨意"去使用mfc的时候.

 

 

方法二.

这种方法才是标准的方法, 也非常简单:

 

  1. HRESULT 
  2. YourDocHostUIHandler::GetDropTarget( IDropTarget *pDropTarget, IDropTarget **ppDropTarget)
  3. {
  4.     //使用用户定义的拖拽
  5.     *ppDropTarget = &YourDropTarget;
  6.     return S_OK;
  7. }

在这个方法中我们告诉WebBrowser,我们使用YourDropTarget代替默认的DropTarget.

 

 

 

 

欢迎拍砖和提问.

谢谢.

 

脱离MFC苦海, 返璞归真,回到纯SDK的怀抱吧~

posted on 2008-09-01 04:17  norsd  阅读(351)  评论(0编辑  收藏  举报

导航