Introduction
Sometimes when you are
using the IE Browser Control inside of a
Visual C++
application, you need to get access to the HTML
elements. We can do it by using standard COM objects
like IWebBrowser2
,
IHTMLDocument2
,
etc. By this method, we can easily implement
features like click button, click anchor, get input
string, get HTML text, etc. Unfortunately, Microsoft
did not provide similar objects for
JavaScript. At
any case, to make control for a
JavaScript
object inside of an HTML page is possible by using
the traditional COM approach. This
article
describes the class
CWebPage
which allows to do it and a technique to
call a
JavaScript
function from Visual C++
code.
How to do
As a result of using the
presented class, it will be easy to
call any
JavaScript
function from C++ code.
For implementing this feature, we should get a
pointer to the
IHTMLDocument2
interface. If we are using the
CHtmlView
class from MFC,
we can get one by using the member function
CHtmlView::GetHtmlDocument()
.
In the case of using
IWebBrowser
or IWebBrowser2
components, the function
get_Document
will bring us the desired interface. Here is an
example:
Collapse | Copy
Code
CComPtr<IDispatch> spDisp = CHtmlView::GetHtmlDocument();
m_webPage.SetDocument(spDisp);
The rest of the things will
be done by the
CWebPage
class.
Here is an example of a JavaScript call without
parameters:
Collapse | Copy
Code
m_webPage.CallJScript("Welcome");
An
example of a
JavaScript call with two parameters will
looks like:
Collapse | Copy
Code
m_webPage.CallJScript("Miltiply","2.34","3.32");
The class implementation
Collapse | Copy
Code
class CWebPage
{
public:
CWebPage();
virtual ~CWebPage();
bool SetDocument(IDispatch* pDisp);
LPDISPATCH GetHtmlDocument() const;
const CString GetLastError() const;
bool GetJScript(CComPtr<IDispatch>& spDisp);
bool GetJScripts(CComPtr<IHTMLElementCollection>& spColl);
CString ScanJScript(CString& strAText,CStringArray& args);
bool CallJScript(const CString strFunc);
bool CallJScript(const CString strFunc,const CString strArg1);
bool CallJScript(const CString strFunc,const CString strArg1,
const CString strArg2);
bool CallJScript(const CString strFunc,const CString strArg1,
const CString strArg2,const CString strArg3);
bool CallJScript(const CString strFunc,const CStringArray& paramArray);
protected:
CComPtr<IHTMLDocument2> m_spDoc;
};
Calling technique
The above mentioned
technique can be split into the following steps:
- Getting a pointer to
the
IHTMLDocument2
interface.
- Getting
IDispatch
for the JavaScript
object in the HTML document.
- Getting the
DISPID
for the given name of the
JavaScript function.
- Putting the parameters
to the
DISPPARAM
structure.
- Calling the
JavaScript
function by using the
Invoke
method of the
IDispatch
interface.
Here is an example of
getting an
IDispatch
pointer to the JavaScript objects:
Collapse | Copy
Code
bool CWebPage::GetJScript(CComPtr<IDispatch>& spDisp)
{
HRESULT hr = m_spDoc->get_Script(&spDisp);
ATLASSERT(SUCCEEDED(hr));
return SUCCEEDED(hr);
}
And here is the final
function to call JavaScript:
Collapse | Copy
Code
CComVariant CWebPage::CallJScript(const CString strFunc,
const CStringArray& paramArray)
{
CComPtr<IDispatch> spScript;
if(!GetJScript(spScript))
{
ShowError("Cannot GetScript");
return false;
}
CComBSTR bstrMember(strFunc);
DISPID dispid = NULL;
HRESULT hr = spScript->GetIDsOfNames(IID_NULL,&bstrMember,1,
LOCALE_SYSTEM_DEFAULT,&dispid);
if(FAILED(hr))
{
ShowError(GetSystemErrorMessage(hr));
return false;
}
const int arraySize = paramArray.GetSize();
DISPPARAMS dispparams;
memset(&dispparams, 0, sizeof dispparams);
dispparams.cArgs = arraySize;
dispparams.rgvarg = new VARIANT[dispparams.cArgs];
dispparams.cNamedArgs = 0;
for( int i = 0; i < arraySize; i++)
{
CComBSTR bstr = paramArray.GetAt(arraySize - 1 - i); bstr.CopyTo(&dispparams.rgvarg[i].bstrVal);
dispparams.rgvarg[i].vt = VT_BSTR;
}
EXCEPINFO excepInfo;
memset(&excepInfo, 0, sizeof excepInfo);
CComVariant vaResult;
UINT nArgErr = (UINT)-1; hr = spScript->Invoke(dispid,IID_NULL,0,
DISPATCH_METHOD,&dispparams,
&vaResult,&excepInfo,&nArgErr);
delete [] dispparams.rgvarg;
if(FAILED(hr))
{
ShowError(GetSystemErrorMessage(hr));
return false;
}
return vaResult;
}
Notes about the demo
To
call a
JavaScript function from the demo, you
should select a function in the tree in the left
window. After this, press the "!" button on the menu
bar.
News
:
1 UCanCode Advance E-XD++
CAD Drawing and Printing Solution
Source Code Solution for C/C++, .NET V2023 is released!
2
UCanCode Advance E-XD++
HMI & SCADA Source Code Solution for C/C++, .NET
V2023 is released!
3
UCanCode Advance E-XD++ GIS SVG Drawing and Printing Solution
Source Code Solution for C/C++, .NET V2023 is
released!
Contact UCanCode Software
To buy the source code or learn more about with: