WebBrowser Introduction to--javascript and C + + interoperability

Source: Internet
Author: User

The WebBrowser control is a Microsoft-provided client-side control for web browsing, and the WebBrowser control is widely used, for example, many mail clients use editable WebBrowser controls as a tool for writing messages. There are also many software with WebBrowser control pop-up pages, such as QQ News home page.

Microsoft's MFC and. NET have WebBrowser controls, both of which are easy to get started with, but because the packaging is so good, it's hard to drill down. Therefore , the WebBrowser described in this article will not use MFC and. NET, but instead use C + + to implement the SDK's WebBrowser.

As this article mainly discusses how to implement JavaScript and C + + interoperability , for how to use the SDK implementation WebBrowser, this article does not do a detailed introduction, the reader can refer to the following article:

Http://blog.csdn.net/norsd/archive/2008/09/13/2921389.aspx

However, although the article describes the SDK implementation WebBrowser, but does not provide a running example, if you want to see the actual performance, you can download the following source code, the source code also includes an interop demo:

SDK implementation WebBrowser and demo code [good text, recommended to see not understand]

1, C + + call WebBrowser in the global function, variables, etc.

(1) Viewing objects in WebBrowser from the perspective of C + +

The objects in WebBrowser can be broadly divided into two categories: DOM objects and objects created using JavaScript. But either way, from a C + + point of view, there are some objects that implement the IDispatch interface, so if you use C + + to manipulate objects in WebBrowser (global functions, variables, DOM), you only need to pass IDispatch.

(2) 3 commonly used functions

When you get the IDispatch interface of an WebBrowser object, you can call the IDispatch invoke method to invoke the object's methods, get the properties of the object, and set the properties of the object. But invoke is the ID that determines which method (or property) of the specified object to invoke, so the method that calls the object through the method (or property) name must first call the IDispatch's GetIDsOfNames method and convert the method (or property) name to an ID before you can invoke the method of the object through the IDispatch invoke method. For ease of operation, three functions were encapsulated to invoke the WebBrowser object's method, read the object's properties, and set the object's properties.

DispID Cwebbrowserbase::findid (IDispatch *pobj, Lpolestr pName) {DispID id = 0;    if (FAILED (Pobj->getidsofnames (iid_null,&pname,1,locale_system_default,&id))) id =-1; return ID;} HRESULT Cwebbrowserbase::invokemethod (IDispatch *pobj, Lpolestr pName, Variant *pvarresult, Variant *p, int cargs) {DIS    PID DispID = Findid (POBJ, pName);    if (DispID = =-1) return E_FAIL;    Dispparams PS;    Ps.cargs = Cargs;    Ps.rgvarg = p;    Ps.cnamedargs = 0;    Ps.rgdispidnamedargs = NULL; Return Pobj->invoke (DispID, Iid_null, Locale_system_default, Dispatch_method, &ps, pvarresult, NULL, NULL);} HRESULT Cwebbrowserbase::getproperty (IDispatch *pobj, Lpolestr pName, VARIANT *pvalue) {DispID DispID = Findid (POBJ, PN    AME);    if (DispID = =-1) return E_FAIL;    Dispparams PS;    Ps.cargs = 0;    Ps.rgvarg = NULL;    Ps.cnamedargs = 0;    Ps.rgdispidnamedargs = NULL; Return Pobj->invoke (DispID, Iid_null, Locale_system_default, Dispatch_propertyget, &ps, PValue, NULL, NULL);} HRESULT Cwebbrowserbase::setproperty (IDispatch *pobj, Lpolestr pName, VARIANT *pvalue) {DispID DispID = Findid (POBJ, PN    AME);    if (DispID = =-1) return E_FAIL;    Dispparams PS;    Ps.cargs = 1;    Ps.rgvarg = PValue;    Ps.cnamedargs = 0;    Ps.rgdispidnamedargs = NULL; Return Pobj->invoke (DispID, Iid_null, Locale_system_default, dispatch_propertyput, &ps, NULL, NULL, NULL);}

  

(3) Calling the global function of the page

In a Web page, All global functions are a method of window , so if you want to call a global function, first get to the Window object of the page, and then call the global function with InvokeMethod, for example, suppose there is a test global function in the page:

<script language= "javascript" type= "Text/javascript" >function Test () {    alert ("You called Test");} </script>

Then, you can call the test function in C + + with the following code:

VARIANT PARAMS[10]; VARIANT ret;//Gets the page windowidispatch *phtmlwindow = Pbrowser->gethtmlwindow ();//page global function test is actually the window's test method, Cwebbrowserbase::invokemethod (Phtmlwindow, L "Test", &ret, params, 0);

  

(4) Methods for calling global objects

In a Web page, All global variables are a property of window , so if you want to invoke a method (or property) of a variable, first get to the Window object of the page, then get the global variable with GetProperty, and then you can call the method of the object. or read and write its properties. For example, suppose you have a globalobject global variable in the page:

<script language= "javascript" type= "Text/javascript" >function globalobject () {this    . Test=function ()    {        alert ("You called Globalobject.test");}    } var globalobject = new Globalobject ();</script>

  

Then, you can call Globalobject's test method using the code:

VARIANT PARAMS[10]; VARIANT ret;//Get page Windowidispatch *phtmlwindow = Pbrowser->gethtmlwindow ();//Get Globalobjectcvariant GlobalObject ;p ARAMS[0].VT = Vt_bstr;params[0].bstrval = L "Globalobject"; Cwebbrowserbase::getproperty (Phtmlwindow, L "Globalobject", &globalobject);// Call Globalobject.testcwebbrowserbase::invokemethod (Globalobject.pdispval, L "Test", &ret, params, 0);

  

2. Methods for invoking clients in Web pages

We've covered how to invoke objects in WebBrowser in C + +, and then we'll show you how to invoke functions and objects in the client in a page:

(1) Call via window.external

Here's an example of how to invoke a function in the client through window.external, assuming that a function named Cppcall is defined in C + +:

void Cppcall () {    MessageBox (NULL, L "You called Cppcall", L "hint (c + +)", 0);}

  

Define an object and implement the IDispatch interface:

Class Clientcall:public idispatch{long _refnum;public:clientcall () {_refnum = 1;    } ~clientcall (void) {}public://IUnknown Methods stdmethodimp QueryInterface (Refiid iid,void**ppvobject)        {*ppvobject = NULL;        if (iid = = IID_IUnknown) *ppvobject = this;        else if (iid = = IID_IDispatch) *ppvobject = (idispatch*) this;            if (*ppvobject) {AddRef ();        return S_OK;    } return e_nointerface;    } stdmethodimp_ (ULONG) AddRef () {return:: InterlockedIncrement (&_refnum);        } stdmethodimp_ (ULONG) Release () {:: InterlockedDecrement (&_refnum);        if (_refnum = = 0) {Delete this;    } return _refnum; }//IDispatch Methods HRESULT _stdcall gettypeinfocount (unsigned int * pctinfo) {return E_notim    PL; } HRESULT _stdcall gettypeinfo (unsigned int itinfo, lcid lcid, ITypeInfo Far* far* pptinfo) {return E_NOTIMPL;          } HRESULT _stdcall GetIDsOfNames (REFIID riid, Olechar far* far* rgsznames, unsigned int cnames,            LCID lcid, dispid far* rgdispid) {if (lstrcmp (rgsznames[0], L "Cppcall") ==0) {        When a Web page calls Window.external.CppCall, this method is called to get the Cppcall id *rgdispid = 100;    } return S_OK;        } HRESULT _stdcall Invoke (dispid dispidmember, REFIID riid, lcid lcid, WORD wflags,    dispparams* pDispParams, variant* pvarresult, excepinfo* pexcepinfo, unsigned int* puargerr)        {if (Dispidmember = = 100) {//page calls Cppcall, or Invoke method Cppcall () according to the obtained ID;    } return S_OK; }};

  

Once the class Clientcall is defined, you can create a Clientcall object and pass it to WebBrowser, Make the Web page can call Cppcall through window.external, to implement these functions, WebBrowser need to implement IDocHostUIHandler interface, and override GetExternal method to return a Clientcall object:

Clientcall *pclientcall;pclientcall = new Clientcall (); Virtual HRESULT stdmethodcalltype getexternal (IDispatch * Ppdispatch) {    //rewrite getexternal returns a Clientcall object    *ppdispatch = Pclientcall;    return S_OK;}

  

Next, you can call it in the Web page:

Window.external.CppCall ()

  

(2) Passing a callback function to a Web page

A typical application of a callback function to a Web page is to use C + + to handle the DOM event in the client (for example, to handle the onclick event of a button), it is important to note that the C + + The difference is that, in the Web page, , so, passing a callback function to a Web page is actually passing an object that implements a call method, so We must define a C + + class and implement the IDispatch interface:

typedef void _stdcall Jsfunction_callback (LPVOID pparam); class jsfunction:public idispatch{long _refnum;    Jsfunction_callback *m_pcallback;        LPVOID m_pparam;public:jsfunction (Jsfunction_callback *pcallback, lpvoid pparam) {_refnum = 1;        M_pcallback = pcallback;    M_pparam = Pparam;    } ~jsfunction (void) {}public://IUnknown Methods stdmethodimp QueryInterface (Refiid iid,void**ppvobject)        {*ppvobject = NULL;        if (iid = = iid_ioleclientsite) *ppvobject = (ioleclientsite*) this;        else if (iid = = IID_IUnknown) *ppvobject = this;            if (*ppvobject) {AddRef ();        return S_OK;    } return e_nointerface;    } stdmethodimp_ (ULONG) AddRef () {return:: InterlockedIncrement (&_refnum);        } stdmethodimp_ (ULONG) Release () {:: InterlockedDecrement (&_refnum);        if (_refnum = = 0) {Delete this;    } return _refnum; }    IDispatch Methods HRESULT _stdcall gettypeinfocount (unsigned int * pctinfo) {return e_notimp    L         } HRESULT _stdcall gettypeinfo (unsigned int itinfo, lcid lcid, ITypeInfo far* far* pptinfo) {    return E_NOTIMPL;          } HRESULT _stdcall GetIDsOfNames (REFIID riid, Olechar far* far* rgsznames, unsigned int cnames, LCID lcid, dispid far* rgdispid) {//The puzzling is that when a Web page calls the function's call method, it does not call the GetIDsOfNames to get the ID of called, but instead directly    Call Invoke return E_NOTIMPL;        } HRESULT _stdcall Invoke (dispid dispidmember, REFIID riid, lcid lcid, WORD wflags,    dispparams* pDispParams, variant* pvarresult, excepinfo* pexcepinfo, unsigned int* puargerr)        {M_pcallback (M_pparam);    return S_OK; }};

  

Next, we can use Jsfunction to pass callbacks to the Web page, and the following code handles the button's OnClick event:

static void _stdcall Button1_onclick (lpvoid pparam) {    mainform *pmainform = (mainform*) pparam;    MessageBox (Pmainform->hwnd, L "You clicked Button1", L "hint (c + +)", 0);} VARIANT params[10];//get Windowidispatch *phtmlwindow = Gethtmlwindow ();//Get documentcvariant DOCUMENT;PARAMS[0].VT = VT _bstr;params[0].bstrval = L "Document"; GetProperty (Phtmlwindow, L "document", &document);//Get button1cvariant BUTTON1;PARAMS[0].VT = vt_bstr;params[0]. Bstrval = L "button1"; InvokeMethod (Document.pdispval, L "getElementById", &button1, params, 1);// The onclick event that handles button1 PARAMS[0].VT = Vt_dispatch;params[0].pdispval = new Jsfunction (Button1_onclick, this); SetProperty (Button1.pdispval, L "onclick", params);

  

SDK implementation WebBrowser and demo code [good text, recommended to see not understand]

WebBrowser Introduction to--javascript and C + + interoperability

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.