王朝网络
分享
 
 
 

Internet Explorer 编程简述(十)响应来自HTML Element的事件通知——几个好用的类

王朝html/css/js·作者佚名  2006-03-12
宽屏版  字体: |||超大  

关键字:HTML Element, Sink

1、概述

实现了对Webbrowser的resuing之后我们便会发现有时候我们还需要处理浏览器中的元素(HTML Element)。这种处理包括主动和被动两个方面,像《FAQ:如何访问WebBrowser的滚动条》、《FAQ:操纵下拉列表》、《FAQ:两种方法访问多层嵌套的frame》等文章所演示的就是主动的处理。通常我们从Webbrowser获得一个Web文档接口(IHTMLDocumentx),从它出发便可访问到浏览器所包含的一切HTML元素。而被动的处理则是在COM技术中称为Sink的技术,我更喜欢的说法是事件通知。当文档的下载进度发生变化时,我们可以获得ProgressChange通知,当Webbrowser下载完HTML文档时,我们可以获得DocumentComplete的通知,而当链接被点击,或图片被拖动时,我们如何获得通知呢?本文希望能够给出部分的答案。

2、HtmlObj Template

如何Sink一个HTML Element并不是本文的重点,其理论我不是太了解,也懒得去搞透彻,所以使用现成的库来实现。CodeProject上的一篇文章《CHtmlObj Template》给出的一个模板类CHtmlObj就非常好用。下面的例子是针对Html Anchor Element的一个实例化。

#include "HtmlObj.h"

class CHtmlAnchorElement : public CHtmlObj<IHTMLAnchorElement,

&DIID_HTMLAnchorEvents>

{

public:

CHtmlAnchorElement(CHtmlDocument2* pParentDoc2);

virtual ~CHtmlAnchorElement();

virtual HRESULT OnInvoke(DISPID dispidMember,REFIID riid,

LCID lcid, WORD wFlags,

DISPPARAMS * pdispparams, VARIANT * pvarResult,

EXCEPINFO * pexcepinfo,

UINT * puArgErr);

};

HRESULT CHtmlAnchorElement::OnInvoke(DISPID dispidMember,

REFIID riid, LCID lcid, WORD wFlags,

DISPPARAMS * pdispparams, VARIANT * pvarResult,

EXCEPINFO * pexcepinfo,

UINT * puArgErr)

{

HRESULT hr = E_NOTIMPL;

switch(dispidMember)

{

case DISPID_HTMLELEMENTEVENTS_ONMOUSEOVER :

{//当鼠标经过链接时,我们在这里获得通知

hr = S_OK;

// TODO: add code to handle on mouse over events

break;

}

case DISPID_HTMLELEMENTEVENTS_ONMOUSEOUT :

{//当鼠标从链接上移开时,我们在这里获得通知,其它的Dispatch ID可根据需要添加

hr = S_OK;

// TODO: add code to handle on mouse out events

break;

}

default:

{

break;

}

}

return hr;

}

当我们得到某个链接的HTML接口指针,便可调用CHtmlAnchorElement继承自CHtmlObj的SetSite(IUnknown *pUnkSite)成员函数传入该接口指针。在CHtmlObj类内部用一个智能指针m_spHtmlObj来保存相应的HTML Element接口指针,所以当上面的ONMOUSEHOVER和ONMOUSEOUT两个事件通知到达时,从m_spHtmlObj就可以访问IHTMLAnchorElement的所有成员,如从href获得链接的Url等,此处不再赘述。

3、CHtmlElements类

有了CHtmlObj之后我们又会发现实践中常常会需要多个相同类型的CHtmlObj。比如包含Frame的网页中每个Frame的HTML Document都需要一个CHtmlObj来Sink其事件。所以我们还需要有效地管理这些相同类型的CHtmlObj。下面是我写的一个简单的模板类CHtmlElements,它通过CMap来管理多个CHtmlObj对象。

template<class THtmlElement> class CHtmlElements

{

typedef CMap<LPDISPATCH, LPDISPATCH, THtmlElement*, THtmlElement*> CMapDispToHtmlElement;

CMapDispToHtmlElement m_htmlElements;

BOOL IsSiteConnected( LPDISPATCH pDisp )

{

THtmlElement *pElement;

return m_htmlElements.Lookup( pDisp, pElement );

}

public:

CHtmlElements(void)

{

}

~CHtmlElements(void)

{//m_htmlElements会自动释放所管理的内存

}

public:

void SetSite( LPDISPATCH pDisp )

{

if ( IsSiteConnected( pDisp ) ) //检查以避免多余的Sink

{

return;

}

THtmlElement *pElement = new THtmlElement; //通过模板类型创建相应的类的实例进行连接

pElement->SetSite( pDisp );

m_htmlElements.SetAt( pDisp, pElement );

}

};

假设我们有一个象CHtmlAnchorElement那样派生自CHtmlObj的类CHtmlDocument2,使用CHtmlElements时这样声明:

typedef CHtmlElements<CHtmlDocument2> CHtmlDocuments;

typedef CHtmlElements<CHtmlAnchorElement> CHtmlAnchors;

class CMyView : public CHtmlView

{

private:

CHtmlDocuments m_htmlDocs;

CHtmlAnchors m_htmlAnchors;

}

在DocumentComplete时就可以这样连接到浏览器的文档对象:

void CMyView ::OnDocumentComplete(LPDISPATCH pDisp, LPCTSTR lpszURL)

{

m_htmlDocs.SetSite(pDisp);

}

如果想一次性连接上文档中所有的Anchor Element,可以通过IHTMLDocument2::get_anchors获得包含所有IHTMLAnchorElement接口指针的IHTMLElementCollection,再遍历其中的每个元素,分别调用m_htmlAnchors.SetSite即可。当然,一次性的Sink全部链接可能并不是个好注意,我更愿意在CHtmlDocument2中响应事件再通过其它手段来访问当前位置的HTML Element。

4、结论

响应HTML Element的事件通知对于浏览器编程来说是一个非常强大的手段,它可以更深入细化地控制浏览器中的文档及其HTML元素,实现更为高级的功能,比如所谓的“超级拖放”(许多多窗口浏览器都提供了该功能,但实际上没有哪个浏览器完美地实现了对URL、文字及图片的拖放)。

5、参考资料

Codeproject: HtmlObj Template

引用地址:《Internet Explorer 编程简述(十)响应来自HTML Element的事件通知——几个好用的类

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有