分享
 
 
 

增强的CHtmlView类,在视图里处理HTML元素事件和交换数据

王朝vc·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

前言

伴随着VC7的诞生,载入IE的对话框成为了新的热点,CDHtmlDialog给不熟悉COM编程的程序员注入了丝丝暖风。处理页面元素的响应事件,与其交换数据都被封装到几组宏内。类似DHTML_EVENT_ONCLICK,DDX_DHtml_Radio的宏被我们添加到实现类里,一切只需等待MFC的魔法开始。

但在视图类方面,吝啬的MFC并没有对其做进一步的封装,能用到的只是IE控件本身几个可怜的事件函数。当然你完全可以这么认为,视图只是观赏IE的成果,这样就不必关心HTML元素的事件了。可贪心和滥用使我既想看到HTML的秀色,又想疯狂的捕获HTML元素的事件。当然,去看MSDN的有关COM的神秘的捕获事件文章(How To Sink HTML Document Events for WebBrowser Host:http://support.microsoft.com/default.aspx?scid=kb;EN-US;q246247),或许你能轻巧的处理事件。对于不熟悉COM的我,能找到CDHtmlDialog和CHtmlView的共同之处,然后重用里面的代码是最最理想的。当然因此产生的两个类CDHtmlSpecEventSink和CDHtmlViewSpec是这一思想的精华。

刨析CDHtmlDialog类

有关COM的知识点可能被我弱化,如果你有兴趣,请翻阅相关的书籍,据说《COM本质论》写的很不错,值得翻阅。如果你不想知道CDHtmlDialog类的有关内容,请直接跳到下一节。

在MFC安装目录下找到下列文件:

afxDhtml.h,dlgdhtml.cpp :CDHtmlDialog 以及其相关类的源代码文件;

afxHtml.h ,viewhtml.cpp:CHtmlView 以及相关类的源代码文件;

如果你研究的更有心得,应该可以完成更为完善的类。这里我们看看CDHtmlDialog类凭什么就可以成为IE控件的宿主,并且与之关联?很快我们就注意到在对话框的OnInitDialog里发现了IE控件的创建。为了便于说明问题,简化代码如下:

BOOL CDHtmlDialog::OnInitDialog()

{

//1.激活对OLE控件容器的支持

AfxEnableControlContainer();

//2. 建立IE控件,当然如果已经有了就Attach之类的东东都被我去掉了

// create the control window ,替换调现有的窗口对象

m_wndBrowser.CreateControl(CLSID_WebBrowser, NULL,

WS_VISIBLE | WS_CHILD, rectClient, this, AFX_IDC_BROWSER);

}

经过这样的处理,我们明白对话框建立后已经附加了一个IE的控件。但我们更关心的是事件怎么被链接和宏化。继续跟踪代码,我们又发现CreateControlSite函数比较可疑,参看MSDN宝典后,我们清楚的知道这个函数就是在控件容器建立控件后需要回调的一个定制管理页面的函数。

BOOL CDHtmlDialog::CreateControlSite(COleControlContainer* pContainer,

COleControlSite** ppSite, UINT /* nID */, REFCLSID /* clsid */)

{

//1.增加一个定制的管理页面

CBrowserControlSite *pBrowserSite =

new CBrowserControlSite(pContainer, this);

if (!pBrowserSite)

return FALSE;

*ppSite = pBrowserSite;

return TRUE;

}

问题又转到CBrowserControlSite 类里,分析其接口,并不多,大都在建立与控件的事件链接。好了,到此为止,我们终于知道诸如ShowUI事件的来历。当然利用宏DECLARE_EVENTSINK_MAP来声明的事件应该与之息息相关。CDHtmlDialog的另一个继承类 CDHtmlEventSink,单单从命名上来看,就觉得其就是我们的目标了。我们去寻找其被调用的地方吧,搜索发现在使用ON_EVENT宏定义的事件里分别是各个EventHook的入口和出口。

代码如下:

void CDHtmlDialog::OnBeforeNavigate(LPDISPATCH pDisp, LPCTSTR szUrl)

{

//1。取消DHTML事件链接

DisconnectDHtmlEvents();

}

void CDHtmlDialog::OnNavigateComplete(LPDISPATCH pDisp, LPCTSTR szUrl)

{

//1。链接DHTML事件

ConnectDHtmlEvents(pdispDoc);}

void CDHtmlDialog::OnDocumentComplete(LPDISPATCH pDisp, LPCTSTR szUrl)

{

//链接DHTML元素事件

ConnectDHtmlElementEvents((((DWORD_PTR)static_cast< CDHtmlSinkHandler* >(this)) - (DWORD_PTR)this));

}

功夫不负有心人,经过一番呆头呆脑的搜索,我们发现了这个事件的来龙去脉。

如果你继续跟踪,会发现还有几个支撑类实现,但我不想再跟了。就在此利用 CDHtmlEventSink类来实现我们的设想吧。

构造类 CDHtmlViewSpec

直接象CDHtmlDialog那样从 CDHtmlEventSink类继承,编译时提示不能使用动态创建。那就让我们继承并实现一个CDHtmlSpecEventSink类吧。

class CDHtmlSpecEventSink: public CDHtmlEventSink

{

public:

//实现这几个抽象方法

virtual const DHtmlEventMapEntry* GetDHtmlEventMap();

virtual BOOL DHtmlEventHook(HRESULT *phr, DISPID dispIdMember, DISPPARAMS *pDispParams,

VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);

virtual HRESULT GetDHtmlDocument(IHTMLDocument2 **pphtmlDoc);

//建立

CDHtmlSpecEventSink();

//给个接口,这个我没有找到在CDHtmlDialog中怎么实现的。

void InitEventSink(IHTMLDocument2* pDoc);

protected:

IHTMLDocument2* m_pDocHtml;

CHtmlView* m_pView;

};

类CDHtmlViewSpec的声明就像下面:

class CDHtmlViewSpec : public CHtmlView ,public CDHtmlSpecEventSink

{

//加入对DHTML事件的支持吧。相关辅助函数也要拷贝哦

};

需要什么就从CDHtmlDialog中拷贝吧,(我最恨你们拷贝程序了,一点技术含量都没有!)

完成了,测试,通过。

使用类CDHtmlViewSpec

使用本类很简单了,直接从CHtmlView继承一个类,然后把文件中的CHtmlView类都改为CDHtmlViewSpec。

添加事件和DDx参考CDHtmlDialog即可。

如果你懒的看帮助,就参考下面的代码吧:

增加事件支持

在你的HTMLView头文件里增加DECLARE_DHTML_EVENT_MAP(),

在cpp文件里增加下列格式的代码:

BEGIN_DHTML_EVENT_MAP(ChtmlExView)

DHTML_EVENT_ONCLICK(_T("btnEnd"), OnButtonEnd)

END_DHTML_EVENT_MAP()

然后添加OnButtonEnd函数的声明和执行体。

增加数据交换的支持

在cpp文件的DoDataExchange里添加下列代码:

void ChtmlExView::DoDataExchange(CDataExchange* pDX)

{

CDHtmlViewSpec::DoDataExchange(pDX);

//增加对Radio控件的数据交互

DDX_DHtml_Radio(pDX,_T("btnControl"),m_iControl);

}

关于作者和代码你可以在这里下载代码和demo程序: http://www.codeproject.com/useritems/luo31.asp

你可以使用和修改本类,但你不应该就此发表类似的文章。引用请标明出处,谢谢!

你可以在这里下载代码和demo程序: http://www.codeproject.com/useritems/luo31.asp

你可以使用和修改本类,但你不应该就此发表类似的文章。引用请标明出处,谢谢!

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
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- 王朝網路 版權所有