外部で文書化されている関連手順は次のとおりです。これは、いくつかの説明を省略して要約されていますが、必要な手順は省略されています。
この例は、2008 年 11 月 25 日の Garry Trinder による記事Using Managed Controls as ActiveX Controlsにも非常によく似ており、この記事のメモもいくつか含めました。
Windows フォーム コントロールを ActiveX コントロールとして公開する
この記事では、.NET の外部で Windows フォーム コントロールを利用する方法について説明します。
コントロールを書く
- Visual Studio 内から新しいコントロール プロジェクトを作成します。私の例はすべて C# ですが、VB.NET も使用できます。
[Garry の記事では、「まず、マネージ ユーザー コントロール プロジェクト (Windows フォーム クラス ライブラリまたはコントロール ライブラリ プロジェクト) を作成します。ユーザー コントロール デザイナーを使用して、(好きな標準コントロールを使用して) カスタム ユーザーコントロールを好きなように設計します。」 ]
コントロールなどをフォームに追加し、コードなどを入れます。
次の using 句を追加します...
using System.Runtime.InteropServices;
using System.Text;
using System.Reflection;
using Microsoft.Win32;
- クラスに属性を付けて、ProgID を取得できるようにします。生成されるため、これは厳密には必要ありませんが、ほとんどの場合、明示的に指定するのが最善です。
[ProgId("Prisoner.PrisonerControl")]
[ClassInterface(ClassInterfaceType.AutoDual)]
これにより、ProgID が割り当てられ、公開されるインターフェイスが「AutoDual」であることも定義されます。これにより、クラスのすべてのパブリックで非静的なメンバーからデフォルト インターフェイスが作成されます。これが望ましくない場合は、他のオプションのいずれかを使用してください。
- アセンブリが COM 相互運用に登録されるように、プロジェクトのプロパティを更新します。
VB.NET を使用している場合は、厳密な名前のアセンブリも必要です。不思議なことに、C# ではそうではありません。コンパイラや CLR の機能ではなく、環境の機能のようです。
- 次の 2 つのメソッドをクラスに追加します。
[ComRegisterFunction()]
public static void RegisterClass ( string key )
{
// Strip off HKEY_CLASSES_ROOT\ from the passed key as I don't need it
StringBuilder sb = new StringBuilder ( key ) ;
sb.Replace(@"HKEY_CLASSES_ROOT\","") ;
// Open the CLSID\{guid} key for write access
RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(),true);
// And create the 'Control' key - this allows it to show up in
// the ActiveX control container
RegistryKey ctrl = k.CreateSubKey ( "Control" ) ;
ctrl.Close ( ) ;
// Next create the CodeBase entry - needed if not string named and GACced.
RegistryKey inprocServer32 = k.OpenSubKey ( "InprocServer32" , true ) ;
inprocServer32.SetValue ( "CodeBase" , Assembly.GetExecutingAssembly().CodeBase ) ;
inprocServer32.Close ( ) ;
// Finally close the main key
k.Close ( ) ;
}
RegisterClass 関数は、ComRegisterFunction に関連付けられています。この静的メソッドは、アセンブリが COM Interop に登録されるときに呼び出されます。ここで行っているのは、「Control」キーワードをレジストリに追加し、さらに CodeBase エントリを追加することだけです。
CodeBase は興味深いものです - .NET コントロールだけではありません。これは、コードが見つかる場所への URL パスを定義します。これは、この例のようにディスク上のアセンブリである場合もあれば、どこかの Web サーバー上のリモート アセンブリである場合もあります。ランタイムがコントロールを作成しようとすると、この URL がプローブされ、必要に応じてコントロールがダウンロードされます。これは、.NET コンポーネントをテストする場合に非常に便利です。.EXE と同じディレクトリ (など) に常駐するという通常の注意事項が適用されないためです。
[ComUnregisterFunction()]
public static void UnregisterClass ( string key )
{
StringBuilder sb = new StringBuilder ( key ) ;
sb.Replace(@"HKEY_CLASSES_ROOT\","") ;
// Open HKCR\CLSID\{guid} for write access
RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(),true);
// Delete the 'Control' key, but don't throw an exception if it does not exist
k.DeleteSubKey ( "Control" , false ) ;
// Next open up InprocServer32
RegistryKey inprocServer32 = k.OpenSubKey ( "InprocServer32" , true ) ;
// And delete the CodeBase key, again not throwing if missing
k.DeleteSubKey ( "CodeBase" , false ) ;
// Finally close the main key
k.Close ( ) ;
}
2 番目の関数は、クラスが登録されていない場合に追加されたレジストリ エントリを削除します。
これで、コントロールをコンパイルしてテストする準備が整いました。
Garry のブログからの追加メモ:
[The] 追加のレジストリ エントリ: Control
、MiscStatus
、TypeLib
および
Version
[作成可能].REG
スクリプトを使用しますが、通常は、登録/登録解除時に呼び出される関数を記述する方が適切です
彼は、レジストリ キーについて詳しく説明しています。
Control
空のサブキーです。TypeLib
TypeLib の GUID にマップされます (これは、assemblyinfo.cs のアセンブリ レベルの GUID です)。
Version
アセンブリ バージョンのメジャーおよびマイナー バージョン番号です。少し興味深いサブキーはMiscStatus
. これは、ここOLEMISC
に記載されている列挙の (ビット単位の) 値で構成される値に設定する必要があります。この列挙型を使用できるようにするには、(および名前空間の適切な「using」ステートメント) への参照を追加します。Microsoft.VisualStudio.OLE.Interop
彼の最後のメモは警告です。
注: これは Excel では問題なく動作するようです (私が行った非常に限られたテストで)。PowerPoint では部分的に動作しますが、Word ではうまく動作しません。おそらく、さらにいくつかのOLEMISC
値がこれを改善する可能性があります。フックする必要があるメッセージがいくつかある可能性があります。おそらく、実装する必要があるインターフェースが他にもいくつかあります...非常に限られた方法でかろうじて動作するようになっただけであるという事実は、これがおそらく深刻な方法で使用したい手法ではないことを示しています.