2012-05-02

VisualStudio2005によるActiveXコントロール開発  [by miyachi]

ActiveXコントロールのプログラミングに関する情報は書籍も含めてVisual-C++6.0のものが多いです。しかしながらもうVC++6.0の時代では無い…と言う事でVisualStudio2005のC++でActiveXコントロールのプロジェクト作成を試してみたのでまとめてみましょう。

まず検索してみると「VS2005 の C/C++ でつくった MFC ActiveX コントロールを HTML へ貼り付ける」と言うブログ記事を発見。書かれているように、MFC ActiveX コントロールを作成して、Cabプロジェクトを追加して、HTMLを作成して表示してみるとさっくり動きました。

おお。これで良いのか…と思ったのですが罠が待っていました。結論を先に言えば「実行しても安全」とマークしておく必要があります。

では簡単に手順を説明します。備忘録なので簡易に書いていますが経験者の方なら不足は無いと思います。また今回はCabファイルは作成しないで話を進めます。

ステップ1:MFC ActiveX コントロールの作成

VisualStudio2005を起動して、[ファイル]-[新規作成]-[プロジェクト] から [Visual C++]-[MFC] を選択して [MFC ActiveX コントロール] にてプロジェクトを作成します。



ここではプロジェクト名はとりあえず "Test" としておきます。とりあえず [MFC ActiveX コントロール ウィザード] の設定は全てデフォルトのままで良いです。[Release] でリビルドすると Release フォルダの下に Test.ocx ファイルが出来ているはずです。

次にテスト用のHTMLファイルを Test.ocx と同じフォルダに作成します。ここでは test1.htm としました。
<HTML><HEAD><body>
ActiveX Test 1<p/>
<object id="Test" width="280" height="280"
CODEBASE="./Test.ocx#Version=1,0,0,0"
classid="CLSID:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX">
</object>
</body></HTML>

"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" には Test.idl を開いて最後の方にある CTestCtrl クラスの uuid をコピペします。
	//  CTestCtrl のクラス情報です。
[ uuid(45510900-0C7E-4A9C-94A6-B88A01D55B66),
helpstring("Test Control"), control ]

さあ、この test1.htm をビルドしたマシンのIEで開いてみましょう。ActiveX実行の警告が出ると思いますが実行を許可してやると、280x280の円が描かれてActiveXコントロールが実行されたはずです。ちなみに円を描くのは TestCtrl.cpp の中の OnDraw() で FillRrect/Ellipse が初期設定されているからですね。



おぉなんだ簡単じゃん!と思ったあなたは甘い。HTMLファイルを修正してサーバにアップしてみましょう。修正するのは Test.ocx ファイルをhttpでURL指定するだけです。もちろん以下のURLは架空ですのでご注意を。
<HTML><HEAD><body>
ActiveX Test 1<p/>
<object id="Test" width="280" height="280"
CODEBASE="http://www.langedge.jp/hogehoge/Test.ocx#Version=1,0,0,0"
classid="CLSID:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX">
</object>
</body></HTML>

これをIEで開いてみると…[×]マークが出て表示されないはずです。残念ながらこれだけではサーバでの実行は出来ません。最初に説明したポイントを更にクリアしないと実行されません。

ステップ2:「実行しても安全」とマークする

ActiveXコントロールを「実行しても安全」としてマークしないとIEでサーバ上のActiveXコントロールは使えません。面倒なのですがそういうWindowsの仕様なのでぶつぶつ言いつつやりましょう。詳しくは Microsoftサポート の「スクリプトおよび初期化を実行しても安全として MFC コントロールにマークする方法」を見て下さい。

1:Cathelp.h/Cathelp.cpp を作成してプロジェクトに追加

先のページに Cathelp.h と Cathelp.cpp のソースがあるのでコピペして作成します。作成したら自分の Test プロジェクトに追加します。追加時に「プリコンパイル済みヘッダーを使用しない」にしておきます。

2:Test.cpp ファイル DllRegisterServer の修正

Test.cpp を開きます。
まず先の Cathelp.h をインクルード。
#include "CatHelp.h"

次に先頭の方で SafeForScripting と SafeForInitializing の定義を追加します。0x7dd95801...の値はそのまま変更しないでコピペして貰って構いません。
const CATID CATID_SafeForScripting     =
{0x7dd95801,0x9882,0x11cf,{0x9f,0xa9,
0x00,0xaa,0x00,0x6c,0x42,0xc4}};
const CATID CATID_SafeForInitializing =
{0x7dd95802,0x9882,0x11cf,{0x9f,0xa9,
0x00,0xaa,0x00,0x6c,0x42,0xc4}};

その下に _ctlid を定義します。
const GUID CDECL BASED_CODE _ctlid =
{ 0xZZZZZZZZ, 0xZZZZ, 0xZZZZ,
{ 0xZZ, 0xZZ, 0xZZ, 0xZZ, 0xZZ, 0xZZ, 0xZZ, 0xZZ } };

ZZZ..の部分の値はコントロールクラス用実装ファイル TestCtrl.cpp の IMPLEMENT_OLECREATE_EX で定義している値をセットします。
// クラス ファクトリおよび GUID を初期化します。
IMPLEMENT_OLECREATE_EX(CTestCtrl, "TEST.TestCtrl.1",
0x45510900, 0xc7e, 0x4a9c, 0x94, 0xa6, 0xb8, 0x8a, 0x1, 0xd5, 0x5b, 0x66)

なので上記のようになっていれば以下を Test.cpp に挿入します。
const GUID CDECL BASED_CODE _ctlid =
{ 0x45510900, 0xc7e, 0x4a9c,
{ 0x94, 0xa6, 0xb8, 0x8a, 0x1, 0xd5, 0x5b, 0x66 } };

最後に以下の部分を DllRegisterServer() の中にコピペで追加挿入します。
  if (FAILED( CreateComponentCategory(
CATID_SafeForScripting,
L"Controls that are safely scriptable") ))
return ResultFromScode(SELFREG_E_CLASS);

if (FAILED( CreateComponentCategory(
CATID_SafeForInitializing,
L"Controls safely initializable from persistent data") ))
return ResultFromScode(SELFREG_E_CLASS);

if (FAILED( RegisterCLSIDInCategory(
_ctlid, CATID_SafeForScripting) ))
return ResultFromScode(SELFREG_E_CLASS);

if (FAILED( RegisterCLSIDInCategory(
_ctlid, CATID_SafeForInitializing) ))
return ResultFromScode(SELFREG_E_CLASS);

以上でビルドすればOKです。ところで DllRegisterServer() はいつ呼ばれるのでしょうか?試しに AfxMessageBox(L"DllRegisterServer"); をDllRegisterServerの先頭に入れてみましょう。メッセージ表示を入れてリビルドすると…メッセージが表示されるはずです。ビルド時には自動的に登録の為に regsvr32.exe が呼ばれ DllRegisterServer() が呼ばれています。

次に新しい Test.ocx ファイルをサーバにアップロードして test2.html を表示してみましょう。表示されましたか?もし表示されない場合にはIEの [インターネットオプション]-[セキュリティ] から [レベルのカスタマイズ] 辺りをチェックしましょう。この辺りの情報はあちこちにあると思いますのでここでは説明しません。

では別のPCから同じ test2.html をIEで開いてみましょう。この時に先の DllRegisterServer() の AfxMessageBox() を有効にしたままだと、ActiveX表示前にメッセージが表示されるはずです。ocxファイルが実行される時に登録の DllRegisterServer() が呼ばれるようです。無事にActiveXコントロールが実行されればこれでお終いです。

昔は inf ファイルで "RegisterServer=yes" とする必要があったんですが、今は必要無いのかな?この辺りでトラブったら、その辺りも調べてみると良いかもしれません。

他にも本当はコード署名で署名する必要とかありますが、その辺りも含めてCabファイルにocxファイルを入れてみるとか試してみるのも手だと思います。

おまけ:Windows7-64bit等のIE9(64bit)でActiveXコントロールが動作しない

どうも64bit版のWindows7環境でIE9(64bit)を使うとActiveXコントロールが動作しないようです。私も設定を含めて色々変更してみましたが駄目でした。

検索してみるとこのブログに、32bit版のIE9を使えとありました。試してみるとさっくり動作しました。どうも64bit環境でActiveXコントロールを動作させるには32bit版のIE9を使うしか無いようです。64bitのActiveXコントロールを作成すれば良いのかな?まぁこの辺りは今後の課題と言うことで…(^^;

何はともあれ今回も色々な先達の皆様の情報で何とかクリアできました。ありがとうございました。本情報も後に続く皆様の何かのお役に立てれば幸いです。
2012-05-02 13:50:59 - miyachi - [プログラミング] -

コメント一覧

コメント無し

コメントを書く

このアイテムは閲覧専用です。コメントの投稿、投票はできません。