わびさびサンプルソース

WindowsやHTML5などのプログラムのサンプルコードやフリーソフトを提供します。

C++からJavaScriptを呼び出す

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);
}



JavaScript側

<!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の呼び出しに成功しました。






わびさびサンプルソース

WindowsやHTML5などのプログラムのサンプルコードやフリーソフトを提供します。