如果大家了解一些com知识,我们知道这里关键的是getidsofnames和invoke方法的实现,因为自动化对象只能通过这样的方式来调用,而不能使用函数指针直接调用虚拟方法,getidsofnames查询指定的函数名的调用id,就是说如果有一个方法是“helloworld”,那么它会先调用getidsofnames方法来查询这个方法是否支持,如果支持则给出该方法的调用id(通过修改rgdispid[out]参数),如果不支持则返回e_notimpl,他的实现简单如下:
| virtual hresult stdmethodcalltype getidsofnames( /* [in] */ refiid riid, /* [size_is][in] */ lpolestr *rgsznames, /* [in] */ uint cnames, /* [in] */ lcid lcid, /* [size_is][out] */ dispid *rgdispid){ *rgdispid=1; return s_ok; } |
这里我们假定了只有一个扩展函数helloworld,如果有多个,我们需要比较rgsznames参数的函数名返回不同的调用id,有了调用id,实现invoke方法就很简单了:
| virtual hresult stdmethodcalltype invoke( /* [in] */ dispid dispidmember, /* [in] */ refiid riid, /* [in] */ lcid lcid, /* [in] */ word wflags, /* [out][in] */ dispparams *pdispparams, /* [out] */ variant *pvarresult, /* [out] */ excepinfo *pexcepinfo, /* [out] */ uint *puargerr){ if(dispidmember==1) { messagebox(0,"hello world","hello",0); //place your code here frmweb->edit1->text="hello world(这也可以?)"; } return s_ok; } |
根据dispidmember的不同实现不同的代码,如果方法是有参数的可以在pdispparams中取得,如果有什么不明白可以参考msdn和一些com的书籍,这里就不详细解释了。
最后我们要做的就是使我们的浏览器知道我们扩展了external,代码如下:
| dochandler = new mydochandler; webbrowser->navigate(widestring(l"e:\\projects\\extweb\\ext.htm")); while(webbrowser->busy) application->processmessages(); icustomdoc *custdoc; webbrowser->document->queryinterface(&custdoc); //取得icustomdoc接口 if (custdoc) { custdoc->setuihandler(dochandler); //设置我们自己的界面处理器 custdoc->release(); } |