Webbrowser-interoperability between JavaScript and C ++

Source: Internet
Author: User

Link: http://www.congci.com/item/webbrowserjavascriptcpp

 

The webbrowser control is a client control provided by Microsoft for Web browsing. The webbrowser control is widely used. For example, many mail clients use the Editable webbrowser control as a tool for writing emails, there are also a lot of software that uses the webbrowser control to pop up webpages, such as the personalized homepage of QQ. For the application of webbrowser, you can also refer to the open-source webim developed by the author. The IM client provided by lesktop open-source webim is implemented using webbrowser:

 

Microsoft's MFC and. Net both have webbrowser controls. Although these two controls are easy to use, they are difficult to gain in-depth insight due to the excellent packaging. Therefore, the webbrowser introduced in this article will not use MFC and. net, but use C ++ to implement the SDK webbrowser.

As this article mainly discusses how to implement JavaScript and C ++ interoperability, this article does not detail how to use SDK to implement webbrowser. Readers can refer to the following article:

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

However, although the article introduces the main points of SDK webbrowser implementation, it does not provide a running example. If you want to see the actual running effect, you can download the following source code, the source code also includes an example of interoperability:

SDK Implementation of webbrowser And Demo code [good text, I do not know]
1. c ++ calls global functions and variables in webbrowser.

(1) view objects in webbrowser from the perspective of C ++

Objects in webbrowser can be roughly divided into DOM objects and objects created using JavaScript. However, from the perspective of C ++, both objects implement the idispatch interface. Therefore, if you use C ++ to operate the objects in webbrowser (global functions, variables, dom), you only need to use idispatch.

(2) three common functions

After obtaining the idispatch interface of the webbrowser object, you can call the invoke method of idispatch to call the object method to obtain the object attributes and set the object attributes. However, invoke uses the ID to determine which method (or attribute) of the specified object to call. Therefore, the method used to call the object through the method (or attribute) name is, you must call the getidsofnames method of idispatch to convert the method (or attribute) name to an ID before calling the object method through the invoke method of idispatch. To facilitate operations, three functions are encapsulated to call the methods of the webbrowser object, read the attributes of the object, and set the attributes of the object.

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)
{
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 = findid (pobj, pname );
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 = findid (pobj, pname );
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 );
} (3) Call global functions on the page

On the webpage, all global functions are a method of window. Therefore, to call a global function, first obtain the window object of the page, and then call the global function with invokemethod, for example, suppose there is a test global function on the page:

<Script language = "JavaScript" type = "text/JavaScript">
Function Test ()
{
Alert ("You called test ");
}
</SCRIPT> you can use the following code to call the test function in C ++:

Variant Params [10];
Variant ret;
// Obtain the page window
Idispatch * phtmlwindow = pbrowser-> gethtmlwindow ();
// The global function test of the page is actually the test method of the window,
Cwebbrowserbase: invokemethod (phtmlwindow, l "test", & ret, Params, 0); (4) Call the Global Object Method

On the webpage, all global variables are an attribute of window. Therefore, to call the method (or attribute) of a variable, you must first obtain the window object of the page, then, get the global variable using getproperty, and then you can call the method of this object or read and write its attributes. For example, assume that the page contains a global variable globalobject:

<Script language = "JavaScript" type = "text/JavaScript">
Function globalobject ()
{
This. test = function ()
{
Alert ("You called globalobject. test ");
}
}

VaR globalobject = new globalobject ();
</SCRIPT> you can use the following code to call the test method of globalobject:

Variant Params [10];
Variant ret;
// Obtain the page window
Idispatch * phtmlwindow = pbrowser-> gethtmlwindow ();
// Obtain globalobject
Cvariant globalobject;
Params [0]. Vt = vt_bstr;
Params [0]. bstrval = l "globalobject ";
Cwebbrowserbase: getproperty (phtmlwindow, l "globalobject", & globalobject );
// Call globalobject. Test
Cwebbrowserbase: invokemethod (globalobject. pdispval, l "test", & ret, Params, 0); 2. Call the client method on the webpage

The above section describes how to call objects in webbrowser in C ++. Next, we will introduce how to call functions and objects in the client on the page:

(1) Use window. External to call

The following example shows how to call a function in the client through window. External. Assume that a function named cppcall is defined in C ++:

Void cppcall ()
{
MessageBox (null, l "you have called cppcall", l "prompt (C ++)", 0 );
} Defines an object and implements 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_notimpl;
}

Hresult _ stdcall gettypeinfo (
Unsigned int itinfo,
Lcid,
Itypeinfo far * pptinfo)
{
Return e_notimpl;
}

Hresult _ stdcall getidsofnames (
Refiid riid,
Olechar far * rgsznames,
Unsigned int cnames,
Lcid,
Dispid far * rgdispid
)
{
If (lstrcmp (rgsznames [0], l "cppcall") = 0)
{
// When the webpage calls window. External. cppcall, this method is called to obtain the ID of cppcall.
* Rgdispid = 100;
}
Return s_ OK;
}

Hresult _ stdcall invoke (
Dispid dispidmember,
Refiid riid,
Lcid,
Word wflags,
Dispparams * pdispparams,
Variant * pvarresult,
Raise info * p1_info,
Unsigned int * puargerr
)
{
If (dispidmember = 100)
{
// When cppcall is called on the webpage, or the invoke method is called Based on the obtained ID
Cppcall ();
}
Return s_ OK;
}
}; After defining the clientcall class, you can create a clientcall object and pass it to webbrowser so that the webpage can use window. external calls cppcall. To implement these functions, webbrowser needs to implement the idochostuihandler interface and rewrite the getexternal method to return a clientcall object:

Clientcall * pclientcall;
Pclientcall = new clientcall ();

Virtual hresult stdmethodcalltype getexternal (idispatch ** ppdispatch)
{
// Override getexternal to return a clientcall object
* Ppdispatch = pclientcall;
Return s_ OK;
} Next, you can call it on the webpage:

Window. External. cppcall () (2) Pass the callback function to the webpage

A typical application for passing callback functions to a webpage is to use C ++ in the client to process DOM events (for example, to process the onclick event of a button). Note that, unlike C ++, the so-called function in a webpage is actually an object with a call method. Therefore, a callback function is passed to the webpage, in fact, it is to pass an object that implements the call method. Therefore, 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_notimpl;
}

Hresult _ stdcall gettypeinfo (
Unsigned int itinfo,
Lcid,
Itypeinfo far * pptinfo)
{
Return e_notimpl;
}

Hresult _ stdcall getidsofnames (
Refiid riid,
Olechar far * rgsznames,
Unsigned int cnames,
Lcid,
Dispid far * rgdispid
)
{
// What is puzzling is that, when a webpage calls the call method of a function, it does not call getidsofnames to obtain the call ID, but directly calls invoke
Return e_notimpl;
}

Hresult _ stdcall invoke (
Dispid dispidmember,
Refiid riid,
Lcid,
Word wflags,
Dispparams * pdispparams,
Variant * pvarresult,
Raise info * p1_info,
Unsigned int * puargerr
)
{
M_pcallback (m_pparam );
Return s_ OK;
}
}; Next, we can use jsfunction to send a callback to the webpage. The following code is used to process the onclick event of the button:

Static void _ stdcall button1_onclick (lpvoid pparam)
{
Mainform * pmainform = (mainform *) pparam;
MessageBox (pmainform-> hwnd, l "you clicked button1", l "prompt (C ++)", 0 );
}

Variant Params [10];

// Obtain the window
Idispatch * phtmlwindow = gethtmlwindow ();

// Obtain the document
Cvariant document;
Params [0]. Vt = vt_bstr;
Params [0]. bstrval = l "document ";
Getproperty (phtmlwindow, l "document", & document );

// Obtain button1
Cvariant button1;
Params [0]. Vt = vt_bstr;
Params [0]. bstrval = l "button1 ";
Invokemethod (document. pdispval, l "getelementbyid", & button1, Params, 1 );

// Process The onclick event of button1
Params [0]. Vt = vt_dispatch;
Params [0]. pdispval = new jsfunction (button1_onclick, this );
Setproperty (button1.pdispval, l "onclick", Params );
From Learning Network http://www.congci.com/item/webbrowserjavascriptcpp

Related Article

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.