C++からIEコントロールで動作しているJavaScriptの関数を呼び出すには、IHTMLDocument2のget_Script()関数で、IDispatchを取得します。 IDispatchのGetIDsOfNames()メソッドで呼び出したい関数名をIdに変換したら、IDispatchのInvoke()メソッドを呼び出すとJavaScriptの関数が実行されます。
#include <tchar.h>
#include <iostream>
#include <string>
#include <shlobj.h>
#include <comdef.h>
#include <comutil.h>
#pragma warning(push)
#pragma warning(disable:4996)
#include <atlbase.h>
#pragma warning(pop)
#include <ExDispid.h>
#include <Mshtml.h>
// Atl.dllの関数ポインタ定義
typedef BOOL(WINAPI *ATLAXWININIT)();
typedef HRESULT(WINAPI *ATLAXGETCONTROL)(HWND, IUnknown **);
// I/F解放用マクロ
#define SAFE_RELEASE( p1 ) if ( p1 ) { p1->Release(); p1 = NULL; }
/*
JavaScriptの呼び出し
*/
HRESULT CallJavaScript
(
IWebBrowser2* pIWebBrowser2
, BSTR funcName // 呼び出したい関数名
, DISPPARAMS* params // パラメータ
, VARIANT* retval // 戻り値
)
{
IDispatch* pIDispatch = NULL;
// IDispatchの取得
HRESULT hResult = pIWebBrowser2->get_Document( &pIDispatch );
if ( S_OK != hResult ) {
goto err;
}
// IHTMLDocument2の取得
IHTMLDocument2* pIHTMLDocument2 = NULL;
hResult = pIDispatch->QueryInterface( __uuidof(IHTMLDocument2), (void**)&pIHTMLDocument2 );
if ( S_OK != hResult ) {
goto err;
}
// IDispatchの取得
IDispatch* pScriptDispatch = NULL;
hResult = pIHTMLDocument2->get_Script( &pScriptDispatch );
if ( S_OK != hResult ) {
goto err;
}
// スクリプト名称をIdに変換
USES_CONVERSION;
OLECHAR FAR* pFuncName = funcName;
DISPID dispId;
hResult = pScriptDispatch->GetIDsOfNames( IID_NULL, &pFuncName, 1, LOCALE_SYSTEM_DEFAULT, &dispId );
if ( S_OK != hResult ) {
goto err;
}
// スクリプトの呼び出し
hResult = pScriptDispatch->Invoke(
dispId
, IID_NULL
, LOCALE_SYSTEM_DEFAULT
, DISPATCH_METHOD
, params
, retval
, NULL
, NULL
);
if ( S_OK != hResult ) {
goto err;
}
err:
SAFE_RELEASE( pIDispatch );
SAFE_RELEASE( pIHTMLDocument2 );
SAFE_RELEASE( pScriptDispatch );
// 処理結果を返す
return( hResult );
}
/*
ブラウザコントロールの生成
*/
int _tmain
(
int argc
, _TCHAR* argv[]
)
{
// ロケール変更(wcoutでユニコードを出力する為)
std::wcout.imbue(std::locale("", std::locale::ctype));
// COMを初期化する
CoInitialize(NULL);
/*
Atl.dllのロード
*/
HMODULE hAtl = NULL;
std::wstring strWindowClassName;
{
struct {
TCHAR* pszDllName; // DLLの名前
TCHAR* pszAtlAxWindowClassName; // ウインドウクラスの名前
} taDllInfo[] = {
{ L"atl110.dll", L"AtlAxWin110" }
,{ L"atl100.dll", L"AtlAxWin100" }
,{ L"atl90.dll" , L"AtlAxWin90" }
,{ L"atl80.dll" , L"AtlAxWin80" }
,{ L"atl71.dll" , L"AtlAxWin71" }
,{ L"atl.dll" , L"AtlAxWin" }
};
for (int nI = 0; nI < _countof(taDllInfo); nI++) {
// DLLをロードしてみる
hAtl = LoadLibrary(taDllInfo[nI].pszDllName);
if (NULL != hAtl) {
// ロードできたので、ウインドウクラス名を取得
strWindowClassName = taDllInfo[nI].pszAtlAxWindowClassName;
break;
}
}
}
if (NULL == hAtl) {
std::wcout << L"atl.dllのロードに失敗しました。" << std::endl;
}
else {
std::wcout << L"atl.dllのロードに成功しました。" << std::endl;
// Atl.dllの関数ポインタ取得
ATLAXWININIT dll_AtlAxWinInit = (ATLAXWININIT)GetProcAddress(hAtl, "AtlAxWinInit");
ATLAXGETCONTROL dll_AtlAxGetControl = (ATLAXGETCONTROL)GetProcAddress(hAtl, "AtlAxGetControl");
// Atlの初期化
dll_AtlAxWinInit();
// ウインドウ矩形
RECT tRect = { 100, 100, 1000, 900 };
/*
ブラウザコントロールの生成
*/
HWND hWnd = CreateWindowEx(
0
, strWindowClassName.c_str()
, L"Shell.Explorer.2"
, WS_OVERLAPPEDWINDOW
| WS_TABSTOP
| WS_VISIBLE
, tRect.left
, tRect.top
, tRect.right - tRect.left
, tRect.bottom - tRect.top
, NULL // 親ウインドウハンドル
, 0
, (HINSTANCE)::GetModuleHandle(NULL)
, 0
);
if (NULL == hWnd) {
std::wcout << L"ブラウザコントロールの生成失敗" << std::endl;
}
else {
std::wcout << L"ブラウザコントロールの生成成功" << std::endl;
CComPtr<IUnknown> pUnknown;
// ATLコントロールの取得
if (S_OK != dll_AtlAxGetControl(hWnd, (IUnknown**)&pUnknown)) {
std::wcout << L"IUnknownの取得失敗" << std::endl;
}
else {
std::wcout << L"IUnknownの取得成功" << std::endl;
CComPtr<IWebBrowser2> pIWebBrowser2;
// IWebBrowser2の取得
pUnknown->QueryInterface(IID_IWebBrowser2, (VOID**)&pIWebBrowser2);
if (NULL == pIWebBrowser2) {
std::wcout << L"IWebBrowser2の取得失敗" << std::endl;
}
else {
std::wcout << L"IWebBrowser2の取得成功" << std::endl;
/*
ホームページを開く
*/
{
TCHAR waFilePath[ MAX_PATH ];
// 実行ファイルのPATH名を得る
::GetModuleFileNameW( NULL, waFilePath, _countof( waFilePath ) );
// ファイル名をHtmlファイルへ変更
TCHAR* pFileNameTop = ::wcsrchr( waFilePath, L'¥¥' ) + 1;
::wcscpy( pFileNameTop, L"Test.html" );
// URL
// CComVariant oNaviGateUrl(L"http://www.yahoo.co.jp");
CComVariant oNaviGateUrl( waFilePath );
CComVariant oNoUse;
pIWebBrowser2->Navigate2(&oNaviGateUrl, &oNoUse, &oNoUse, &oNoUse, &oNoUse);
}
// 時間待ち(テスト用)
::MessageBox(NULL, L"HTMLが表示されたら、OKを押下するとJavaScriptを呼び出します。", L"C++からのJavaScript呼び出し", MB_OK);
/*
JavaScriptの呼び出し
*/
{
DISPPARAMS empty = { NULL, NULL, 0, 0 };
VARIANT retval;
HRESULT hResult = CallJavaScript( pIWebBrowser2, L"TestScript", &empty, &retval );
if ( S_OK == hResult ) {
std::wcout << L"JavaScriptの呼び出しに成功しました。" << std::endl;
}
else {
std::wcout << L"JavaScriptの呼び出しに失敗しました。" << std::endl;
}
}
// 時間待ち(テスト用)
::MessageBox(NULL, L"OKを押下するとブラウザを閉じます。", L"ブラウザコントロールの生成", MB_OK);
}
}
// ウインドウの破棄
::DestroyWindow( hWnd );
}
// Atl.dllの破棄
FreeLibrary(hAtl);
}
// COMの使用終了
CoUninitialize();
// 正常終了
return(0);
}
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="content-language" content="ja">
<title>C++からJavaScriptの関数を呼び出す。</title>
<style>
function TestScript() {
alert( "C++から呼び出されました。" );
};
</style>
<script>
</script>
</head>
<body>
C++からJavaScriptの関数を呼び出す。
<br/>
</body>
</html>
atl.dllのロードに成功しました。 ブラウザコントロールの生成成功 IUnknownの取得成功 IWebBrowser2の取得成功 JavaScriptの呼び出しに成功しました。